@eocrm/design-system 0.0.0-stage → 0.6.17

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 (897) hide show
  1. package/AI-PRIMER.md +341 -0
  2. package/README.md +262 -2
  3. package/docs/components/Accordion.md +114 -0
  4. package/docs/components/AgentAvatar.md +58 -0
  5. package/docs/components/Alert.md +81 -0
  6. package/docs/components/AppLayout.md +70 -0
  7. package/docs/components/Avatar.md +49 -0
  8. package/docs/components/AvatarGroup.md +47 -0
  9. package/docs/components/Badge.md +60 -0
  10. package/docs/components/Banner.md +89 -0
  11. package/docs/components/BrandIcon.md +32 -0
  12. package/docs/components/Breadcrumb.md +72 -0
  13. package/docs/components/Button.md +107 -0
  14. package/docs/components/ButtonGroup.md +78 -0
  15. package/docs/components/Calendar.md +158 -0
  16. package/docs/components/Card.md +165 -0
  17. package/docs/components/CatalogPicker.md +83 -0
  18. package/docs/components/Chart.md +114 -0
  19. package/docs/components/ChatBubble.md +55 -0
  20. package/docs/components/ChatLauncher.md +97 -0
  21. package/docs/components/Checkbox.md +55 -0
  22. package/docs/components/CircularProgress.md +53 -0
  23. package/docs/components/Cluster.md +96 -0
  24. package/docs/components/Code.md +35 -0
  25. package/docs/components/CodeBlock.md +67 -0
  26. package/docs/components/ColorPicker.md +115 -0
  27. package/docs/components/ConfirmationPopover.md +70 -0
  28. package/docs/components/Constrain.md +39 -0
  29. package/docs/components/CurrencySelect.md +57 -0
  30. package/docs/components/CursorPagination.md +43 -0
  31. package/docs/components/DashboardCanvas.md +79 -0
  32. package/docs/components/DashboardWidget.md +131 -0
  33. package/docs/components/DataTable.md +88 -0
  34. package/docs/components/DatePicker.md +68 -0
  35. package/docs/components/DateRangePicker.md +71 -0
  36. package/docs/components/DateStrip.md +56 -0
  37. package/docs/components/DefinitionList.md +82 -0
  38. package/docs/components/Divider.md +57 -0
  39. package/docs/components/Dot.md +26 -0
  40. package/docs/components/Drawer.md +94 -0
  41. package/docs/components/DropdownMenu.md +299 -0
  42. package/docs/components/EmojiPicker.md +84 -0
  43. package/docs/components/EmptyState.md +55 -0
  44. package/docs/components/EntityChip.md +102 -0
  45. package/docs/components/ErrorState.md +72 -0
  46. package/docs/components/Field.md +91 -0
  47. package/docs/components/FileUpload.md +109 -0
  48. package/docs/components/FilterChip.md +88 -0
  49. package/docs/components/FlowCanvas.md +108 -0
  50. package/docs/components/FormRow.md +31 -0
  51. package/docs/components/FormSection.md +37 -0
  52. package/docs/components/Grid.md +103 -0
  53. package/docs/components/Highlight.md +75 -0
  54. package/docs/components/HighlightedText.md +50 -0
  55. package/docs/components/IconPicker.md +134 -0
  56. package/docs/components/IconTile.md +30 -0
  57. package/docs/components/Image.md +84 -0
  58. package/docs/components/ImageCrop.md +163 -0
  59. package/docs/components/Indent.md +31 -0
  60. package/docs/components/InlineDatePicker.md +58 -0
  61. package/docs/components/InlineDateRangePicker.md +57 -0
  62. package/docs/components/Input.md +54 -0
  63. package/docs/components/Kanban.md +122 -0
  64. package/docs/components/Kbd.md +41 -0
  65. package/docs/components/Lightbox.md +105 -0
  66. package/docs/components/Link.md +65 -0
  67. package/docs/components/LinkCard.md +41 -0
  68. package/docs/components/LiquidEditor.md +84 -0
  69. package/docs/components/List.md +68 -0
  70. package/docs/components/LiveRegion.md +29 -0
  71. package/docs/components/LocaleProvider.md +25 -0
  72. package/docs/components/Logo.md +41 -0
  73. package/docs/components/Masonry.md +48 -0
  74. package/docs/components/MediaTile.md +95 -0
  75. package/docs/components/Modal.md +107 -0
  76. package/docs/components/MoneyInput.md +62 -0
  77. package/docs/components/OptionsPicker.md +123 -0
  78. package/docs/components/OtpInput.md +65 -0
  79. package/docs/components/Page.md +35 -0
  80. package/docs/components/PageHeader.md +133 -0
  81. package/docs/components/Pagination.md +44 -0
  82. package/docs/components/Palette.md +32 -0
  83. package/docs/components/PasswordInput.md +45 -0
  84. package/docs/components/PasswordStrengthMeter.md +27 -0
  85. package/docs/components/PersonDisplay.md +153 -0
  86. package/docs/components/PhoneInput.md +54 -0
  87. package/docs/components/PillMenu.md +91 -0
  88. package/docs/components/Popover.md +127 -0
  89. package/docs/components/Progress.md +56 -0
  90. package/docs/components/QrCode.md +34 -0
  91. package/docs/components/Radio.md +37 -0
  92. package/docs/components/RadioGroup.md +56 -0
  93. package/docs/components/Rail.md +191 -0
  94. package/docs/components/RelativeDateInput.md +114 -0
  95. package/docs/components/RichText.md +44 -0
  96. package/docs/components/RichTextEditor.md +112 -0
  97. package/docs/components/Screen.md +37 -0
  98. package/docs/components/ScrollArea.md +39 -0
  99. package/docs/components/Select.md +131 -0
  100. package/docs/components/SettingRow.md +98 -0
  101. package/docs/components/Skeleton.md +68 -0
  102. package/docs/components/Slider.md +92 -0
  103. package/docs/components/SlotGrid.md +55 -0
  104. package/docs/components/SocialButton.md +31 -0
  105. package/docs/components/Sortable.md +127 -0
  106. package/docs/components/SortableGroup.md +52 -0
  107. package/docs/components/Sparkline.md +51 -0
  108. package/docs/components/Split.md +76 -0
  109. package/docs/components/Stack.md +59 -0
  110. package/docs/components/StagePath.md +66 -0
  111. package/docs/components/StatGroup.md +61 -0
  112. package/docs/components/StatTile.md +58 -0
  113. package/docs/components/Sticky.md +69 -0
  114. package/docs/components/Switch.md +89 -0
  115. package/docs/components/Table.md +184 -0
  116. package/docs/components/TableOfContents.md +76 -0
  117. package/docs/components/Tabs.md +94 -0
  118. package/docs/components/Text.md +63 -0
  119. package/docs/components/Textarea.md +59 -0
  120. package/docs/components/Thread.md +52 -0
  121. package/docs/components/TimeField.md +70 -0
  122. package/docs/components/Timeline.md +57 -0
  123. package/docs/components/Title.md +54 -0
  124. package/docs/components/ToastViewport.md +61 -0
  125. package/docs/components/Tooltip.md +63 -0
  126. package/docs/components/TopBar.md +214 -0
  127. package/docs/components/Tour.md +85 -0
  128. package/docs/components/TreeView.md +113 -0
  129. package/docs/components/VisuallyHidden.md +43 -0
  130. package/docs/components/WidgetPreview.md +54 -0
  131. package/docs/components/useBelowBreakpoint.md +11 -0
  132. package/docs/components/useMonth.md +18 -0
  133. package/docs/setup.md +51 -0
  134. package/docs/theming.md +95 -0
  135. package/docs/tokens.md +123 -0
  136. package/docs/transient-state.md +56 -0
  137. package/package.json +82 -4
  138. package/src/_meta/manifest.ts +293 -0
  139. package/src/app/AppProvider.tsx +78 -0
  140. package/src/app/index.ts +3 -0
  141. package/src/app/themeTokens.ts +95 -0
  142. package/src/calendar/dateMath.ts +114 -0
  143. package/src/calendar/formatters.ts +75 -0
  144. package/src/calendar/index.ts +39 -0
  145. package/src/calendar/types.ts +36 -0
  146. package/src/calendar/useAgenda.ts +70 -0
  147. package/src/calendar/useDay.ts +51 -0
  148. package/src/calendar/useMonth.ts +82 -0
  149. package/src/calendar/useWeek.ts +62 -0
  150. package/src/calendar/weekInfo.ts +83 -0
  151. package/src/components/Accordion/Accordion.module.scss +304 -0
  152. package/src/components/Accordion/Accordion.tokens.scss +64 -0
  153. package/src/components/Accordion/Accordion.tsx +272 -0
  154. package/src/components/Accordion/AccordionContent.tsx +36 -0
  155. package/src/components/Accordion/AccordionItem.tsx +66 -0
  156. package/src/components/Accordion/AccordionTrigger.tsx +121 -0
  157. package/src/components/Accordion/context.ts +47 -0
  158. package/src/components/Accordion/index.ts +14 -0
  159. package/src/components/Alert/Alert.module.scss +92 -0
  160. package/src/components/Alert/Alert.tokens.scss +60 -0
  161. package/src/components/Alert/Alert.tsx +136 -0
  162. package/src/components/Alert/index.ts +2 -0
  163. package/src/components/AppLayout/AppLayout.module.scss +130 -0
  164. package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
  165. package/src/components/AppLayout/AppLayout.tsx +211 -0
  166. package/src/components/AppLayout/index.ts +2 -0
  167. package/src/components/Avatar/AgentAvatar.module.scss +117 -0
  168. package/src/components/Avatar/AgentAvatar.tsx +122 -0
  169. package/src/components/Avatar/Avatar.module.scss +181 -0
  170. package/src/components/Avatar/Avatar.tokens.scss +107 -0
  171. package/src/components/Avatar/Avatar.tsx +210 -0
  172. package/src/components/Avatar/AvatarGroup.module.scss +128 -0
  173. package/src/components/Avatar/AvatarGroup.tsx +119 -0
  174. package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
  175. package/src/components/Avatar/index.ts +6 -0
  176. package/src/components/Badge/Badge.module.scss +124 -0
  177. package/src/components/Badge/Badge.tokens.scss +74 -0
  178. package/src/components/Badge/Badge.tsx +164 -0
  179. package/src/components/Badge/index.ts +2 -0
  180. package/src/components/Banner/Banner.module.scss +73 -0
  181. package/src/components/Banner/Banner.tokens.scss +51 -0
  182. package/src/components/Banner/Banner.tsx +138 -0
  183. package/src/components/Banner/index.ts +2 -0
  184. package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
  185. package/src/components/BrandIcon/BrandIcon.tsx +99 -0
  186. package/src/components/BrandIcon/index.ts +2 -0
  187. package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
  188. package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
  189. package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
  190. package/src/components/Breadcrumb/index.ts +2 -0
  191. package/src/components/Button/Button.module.scss +167 -0
  192. package/src/components/Button/Button.tokens.scss +90 -0
  193. package/src/components/Button/Button.tsx +205 -0
  194. package/src/components/Button/index.ts +2 -0
  195. package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
  196. package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
  197. package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
  198. package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
  199. package/src/components/ButtonGroup/context.ts +45 -0
  200. package/src/components/ButtonGroup/index.ts +2 -0
  201. package/src/components/Calendar/AgendaView.module.scss +231 -0
  202. package/src/components/Calendar/AgendaView.tsx +214 -0
  203. package/src/components/Calendar/AllDayBand.module.scss +18 -0
  204. package/src/components/Calendar/AllDayBand.tsx +75 -0
  205. package/src/components/Calendar/Calendar.module.scss +23 -0
  206. package/src/components/Calendar/Calendar.tokens.scss +262 -0
  207. package/src/components/Calendar/Calendar.tsx +370 -0
  208. package/src/components/Calendar/DayCell.module.scss +30 -0
  209. package/src/components/Calendar/DayCell.tsx +50 -0
  210. package/src/components/Calendar/DayView.module.scss +10 -0
  211. package/src/components/Calendar/DayView.tsx +163 -0
  212. package/src/components/Calendar/EventChip.module.scss +171 -0
  213. package/src/components/Calendar/EventChip.tsx +115 -0
  214. package/src/components/Calendar/HourGrid.module.scss +123 -0
  215. package/src/components/Calendar/HourGrid.tsx +381 -0
  216. package/src/components/Calendar/MonthView.module.scss +99 -0
  217. package/src/components/Calendar/MonthView.tsx +296 -0
  218. package/src/components/Calendar/TimedEvent.module.scss +205 -0
  219. package/src/components/Calendar/TimedEvent.tsx +247 -0
  220. package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
  221. package/src/components/Calendar/ViewSwitcher.tsx +47 -0
  222. package/src/components/Calendar/WeekView.module.scss +10 -0
  223. package/src/components/Calendar/WeekView.tsx +137 -0
  224. package/src/components/Calendar/eventColor.ts +60 -0
  225. package/src/components/Calendar/index.ts +18 -0
  226. package/src/components/Calendar/types.ts +451 -0
  227. package/src/components/Calendar/useEventDrag.ts +783 -0
  228. package/src/components/Calendar/utils.ts +622 -0
  229. package/src/components/Card/Card.module.scss +264 -0
  230. package/src/components/Card/Card.tokens.scss +55 -0
  231. package/src/components/Card/Card.tsx +170 -0
  232. package/src/components/Card/CardBody.tsx +45 -0
  233. package/src/components/Card/CardHeader.tsx +113 -0
  234. package/src/components/Card/CardList.tsx +24 -0
  235. package/src/components/Card/CardListRow.tsx +24 -0
  236. package/src/components/Card/index.ts +7 -0
  237. package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
  238. package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
  239. package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
  240. package/src/components/CatalogPicker/index.ts +2 -0
  241. package/src/components/Chart/Chart.module.scss +287 -0
  242. package/src/components/Chart/Chart.tokens.scss +63 -0
  243. package/src/components/Chart/Chart.tsx +607 -0
  244. package/src/components/Chart/ChartLegend.tsx +99 -0
  245. package/src/components/Chart/ChartTable.tsx +62 -0
  246. package/src/components/Chart/ChartTooltip.tsx +91 -0
  247. package/src/components/Chart/chartModel.ts +689 -0
  248. package/src/components/Chart/index.ts +2 -0
  249. package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
  250. package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
  251. package/src/components/ChatBubble/ChatBubble.tsx +61 -0
  252. package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
  253. package/src/components/ChatBubble/index.ts +3 -0
  254. package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
  255. package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
  256. package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
  257. package/src/components/ChatLauncher/index.ts +2 -0
  258. package/src/components/ChatLauncher/isAtBottom.ts +12 -0
  259. package/src/components/Checkbox/Checkbox.module.scss +147 -0
  260. package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
  261. package/src/components/Checkbox/Checkbox.tsx +188 -0
  262. package/src/components/Checkbox/index.ts +2 -0
  263. package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
  264. package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
  265. package/src/components/CircularProgress/CircularProgress.tsx +139 -0
  266. package/src/components/CircularProgress/index.ts +7 -0
  267. package/src/components/Cluster/Cluster.module.scss +145 -0
  268. package/src/components/Cluster/Cluster.tokens.scss +11 -0
  269. package/src/components/Cluster/Cluster.tsx +215 -0
  270. package/src/components/Cluster/index.ts +2 -0
  271. package/src/components/Code/Code.module.scss +28 -0
  272. package/src/components/Code/Code.tokens.scss +15 -0
  273. package/src/components/Code/Code.tsx +44 -0
  274. package/src/components/Code/index.ts +2 -0
  275. package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
  276. package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
  277. package/src/components/CodeBlock/CodeBlock.tsx +274 -0
  278. package/src/components/CodeBlock/highlight.ts +179 -0
  279. package/src/components/CodeBlock/index.ts +8 -0
  280. package/src/components/CodeBlock/sampleSync.ts +42 -0
  281. package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
  282. package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
  283. package/src/components/ColorPicker/ColorPicker.tsx +367 -0
  284. package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
  285. package/src/components/ColorPicker/SVSquare.tsx +189 -0
  286. package/src/components/ColorPicker/colorMath.ts +141 -0
  287. package/src/components/ColorPicker/index.ts +6 -0
  288. package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
  289. package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
  290. package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
  291. package/src/components/ConfirmationPopover/index.ts +2 -0
  292. package/src/components/Constrain/Constrain.module.scss +99 -0
  293. package/src/components/Constrain/Constrain.tsx +79 -0
  294. package/src/components/Constrain/index.ts +2 -0
  295. package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
  296. package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
  297. package/src/components/CurrencySelect/index.ts +3 -0
  298. package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
  299. package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
  300. package/src/components/CursorPagination/CursorPagination.tsx +121 -0
  301. package/src/components/CursorPagination/index.ts +2 -0
  302. package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
  303. package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
  304. package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
  305. package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
  306. package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
  307. package/src/components/DashboardCanvas/engine.ts +363 -0
  308. package/src/components/DashboardCanvas/index.ts +9 -0
  309. package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
  310. package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
  311. package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
  312. package/src/components/DashboardWidget/index.ts +7 -0
  313. package/src/components/DataTable/BodyRow.tsx +197 -0
  314. package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
  315. package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
  316. package/src/components/DataTable/DataTable.module.scss +511 -0
  317. package/src/components/DataTable/DataTable.tokens.scss +80 -0
  318. package/src/components/DataTable/DataTable.tsx +734 -0
  319. package/src/components/DataTable/HeaderCell.module.scss +215 -0
  320. package/src/components/DataTable/HeaderCell.tsx +440 -0
  321. package/src/components/DataTable/columnShift.ts +117 -0
  322. package/src/components/DataTable/index.ts +23 -0
  323. package/src/components/DataTable/pinStyle.ts +47 -0
  324. package/src/components/DataTable/reorderColumns.ts +66 -0
  325. package/src/components/DataTable/types.ts +289 -0
  326. package/src/components/DataTable/useColumnDragShift.ts +216 -0
  327. package/src/components/DataTable/useDataTable.ts +372 -0
  328. package/src/components/DataTable/useResizeHandle.ts +97 -0
  329. package/src/components/DatePicker/DatePicker.module.scss +180 -0
  330. package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
  331. package/src/components/DatePicker/DatePicker.tsx +664 -0
  332. package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
  333. package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
  334. package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
  335. package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
  336. package/src/components/DatePicker/index.ts +4 -0
  337. package/src/components/DatePicker/utils.ts +364 -0
  338. package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
  339. package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
  340. package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
  341. package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
  342. package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
  343. package/src/components/DateRangePicker/index.ts +5 -0
  344. package/src/components/DateRangePicker/utils.ts +151 -0
  345. package/src/components/DateStrip/DateStrip.module.scss +78 -0
  346. package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
  347. package/src/components/DateStrip/DateStrip.tsx +205 -0
  348. package/src/components/DateStrip/index.ts +2 -0
  349. package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
  350. package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
  351. package/src/components/DefinitionList/DefinitionList.tsx +198 -0
  352. package/src/components/DefinitionList/index.ts +9 -0
  353. package/src/components/Divider/Divider.module.scss +144 -0
  354. package/src/components/Divider/Divider.tokens.scss +21 -0
  355. package/src/components/Divider/Divider.tsx +103 -0
  356. package/src/components/Divider/index.ts +2 -0
  357. package/src/components/Dot/Dot.module.scss +40 -0
  358. package/src/components/Dot/Dot.tokens.scss +4 -0
  359. package/src/components/Dot/Dot.tsx +45 -0
  360. package/src/components/Dot/index.ts +2 -0
  361. package/src/components/Drawer/Body.tsx +23 -0
  362. package/src/components/Drawer/Close.tsx +35 -0
  363. package/src/components/Drawer/Content.tsx +93 -0
  364. package/src/components/Drawer/Drawer.module.scss +232 -0
  365. package/src/components/Drawer/Drawer.tokens.scss +38 -0
  366. package/src/components/Drawer/Drawer.tsx +23 -0
  367. package/src/components/Drawer/DrawerRoot.tsx +190 -0
  368. package/src/components/Drawer/Footer.tsx +24 -0
  369. package/src/components/Drawer/Header.tsx +64 -0
  370. package/src/components/Drawer/Overlay.tsx +82 -0
  371. package/src/components/Drawer/context.ts +44 -0
  372. package/src/components/Drawer/index.ts +12 -0
  373. package/src/components/Drawer/useDragToClose.ts +149 -0
  374. package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
  375. package/src/components/DropdownMenu/Content.tsx +419 -0
  376. package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
  377. package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
  378. package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
  379. package/src/components/DropdownMenu/Group.tsx +76 -0
  380. package/src/components/DropdownMenu/Item.tsx +148 -0
  381. package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
  382. package/src/components/DropdownMenu/Radio.tsx +178 -0
  383. package/src/components/DropdownMenu/Root.tsx +100 -0
  384. package/src/components/DropdownMenu/Sub.tsx +332 -0
  385. package/src/components/DropdownMenu/Trigger.tsx +76 -0
  386. package/src/components/DropdownMenu/context.ts +65 -0
  387. package/src/components/DropdownMenu/index.ts +20 -0
  388. package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
  389. package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
  390. package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
  391. package/src/components/EmojiPicker/emojiData.ts +245 -0
  392. package/src/components/EmojiPicker/index.ts +3 -0
  393. package/src/components/EmptyState/EmptyState.module.scss +102 -0
  394. package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
  395. package/src/components/EmptyState/EmptyState.tsx +112 -0
  396. package/src/components/EmptyState/index.ts +7 -0
  397. package/src/components/EntityChip/EntityChip.module.scss +275 -0
  398. package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
  399. package/src/components/EntityChip/EntityChip.tsx +649 -0
  400. package/src/components/EntityChip/index.ts +10 -0
  401. package/src/components/ErrorState/ErrorState.module.scss +105 -0
  402. package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
  403. package/src/components/ErrorState/ErrorState.tsx +125 -0
  404. package/src/components/ErrorState/index.ts +8 -0
  405. package/src/components/Field/Field.module.scss +46 -0
  406. package/src/components/Field/Field.tsx +185 -0
  407. package/src/components/Field/index.ts +2 -0
  408. package/src/components/FileUpload/FileUpload.module.scss +187 -0
  409. package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
  410. package/src/components/FileUpload/FileUpload.tsx +569 -0
  411. package/src/components/FileUpload/formatBytes.ts +34 -0
  412. package/src/components/FileUpload/iconForFile.ts +40 -0
  413. package/src/components/FileUpload/index.ts +2 -0
  414. package/src/components/FilterChip/FilterChip.module.scss +61 -0
  415. package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
  416. package/src/components/FilterChip/FilterChip.tsx +208 -0
  417. package/src/components/FilterChip/index.ts +5 -0
  418. package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
  419. package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
  420. package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
  421. package/src/components/FlowCanvas/FlowControls.tsx +46 -0
  422. package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
  423. package/src/components/FlowCanvas/FlowNode.tsx +76 -0
  424. package/src/components/FlowCanvas/edgePath.ts +85 -0
  425. package/src/components/FlowCanvas/index.ts +4 -0
  426. package/src/components/FlowCanvas/layout.ts +148 -0
  427. package/src/components/FlowCanvas/spatialNav.ts +76 -0
  428. package/src/components/FlowCanvas/types.ts +59 -0
  429. package/src/components/FlowCanvas/useViewport.ts +122 -0
  430. package/src/components/FormRow/FormRow.module.scss +2 -0
  431. package/src/components/FormRow/FormRow.tsx +37 -0
  432. package/src/components/FormRow/index.ts +2 -0
  433. package/src/components/FormSection/FormSection.module.scss +24 -0
  434. package/src/components/FormSection/FormSection.tsx +46 -0
  435. package/src/components/FormSection/index.ts +2 -0
  436. package/src/components/Grid/Grid.module.scss +162 -0
  437. package/src/components/Grid/Grid.tokens.scss +13 -0
  438. package/src/components/Grid/Grid.tsx +226 -0
  439. package/src/components/Grid/GridItem.tsx +77 -0
  440. package/src/components/Grid/index.ts +11 -0
  441. package/src/components/Highlight/Highlight.module.scss +43 -0
  442. package/src/components/Highlight/Highlight.tokens.scss +35 -0
  443. package/src/components/Highlight/Highlight.tsx +164 -0
  444. package/src/components/Highlight/HighlightOverlay.tsx +100 -0
  445. package/src/components/Highlight/index.ts +2 -0
  446. package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
  447. package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
  448. package/src/components/HighlightedText/HighlightedText.tsx +50 -0
  449. package/src/components/HighlightedText/highlightRanges.ts +44 -0
  450. package/src/components/HighlightedText/index.ts +2 -0
  451. package/src/components/IconPicker/IconPicker.module.scss +175 -0
  452. package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
  453. package/src/components/IconPicker/IconPicker.tsx +629 -0
  454. package/src/components/IconPicker/index.ts +9 -0
  455. package/src/components/IconTile/IconTile.module.scss +57 -0
  456. package/src/components/IconTile/IconTile.tokens.scss +16 -0
  457. package/src/components/IconTile/IconTile.tsx +91 -0
  458. package/src/components/IconTile/index.ts +2 -0
  459. package/src/components/Image/Image.module.scss +266 -0
  460. package/src/components/Image/Image.tokens.scss +55 -0
  461. package/src/components/Image/Image.tsx +342 -0
  462. package/src/components/Image/index.ts +2 -0
  463. package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
  464. package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
  465. package/src/components/ImageCrop/ImageCrop.tsx +542 -0
  466. package/src/components/ImageCrop/cropGeometry.ts +120 -0
  467. package/src/components/ImageCrop/extractCropBlob.ts +140 -0
  468. package/src/components/ImageCrop/index.ts +11 -0
  469. package/src/components/ImageCrop/useCropPreview.ts +161 -0
  470. package/src/components/Indent/Indent.module.scss +33 -0
  471. package/src/components/Indent/Indent.tokens.scss +10 -0
  472. package/src/components/Indent/Indent.tsx +46 -0
  473. package/src/components/Indent/index.ts +2 -0
  474. package/src/components/Input/Input.module.scss +99 -0
  475. package/src/components/Input/Input.tokens.scss +54 -0
  476. package/src/components/Input/Input.tsx +105 -0
  477. package/src/components/Input/Suggestions.tsx +260 -0
  478. package/src/components/Input/index.ts +2 -0
  479. package/src/components/Kanban/Kanban.module.scss +39 -0
  480. package/src/components/Kanban/Kanban.tokens.scss +15 -0
  481. package/src/components/Kanban/Kanban.tsx +951 -0
  482. package/src/components/Kanban/index.ts +7 -0
  483. package/src/components/Kbd/Kbd.module.scss +47 -0
  484. package/src/components/Kbd/Kbd.tokens.scss +26 -0
  485. package/src/components/Kbd/Kbd.tsx +73 -0
  486. package/src/components/Kbd/index.ts +2 -0
  487. package/src/components/Lightbox/Lightbox.module.scss +283 -0
  488. package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
  489. package/src/components/Lightbox/Lightbox.tsx +506 -0
  490. package/src/components/Lightbox/index.ts +2 -0
  491. package/src/components/Link/Link.module.scss +78 -0
  492. package/src/components/Link/Link.tokens.scss +28 -0
  493. package/src/components/Link/Link.tsx +114 -0
  494. package/src/components/Link/index.ts +2 -0
  495. package/src/components/LinkCard/LinkCard.module.scss +92 -0
  496. package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
  497. package/src/components/LinkCard/LinkCard.tsx +72 -0
  498. package/src/components/LinkCard/index.ts +2 -0
  499. package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
  500. package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
  501. package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
  502. package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
  503. package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
  504. package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
  505. package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
  506. package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
  507. package/src/components/LiquidEditor/index.ts +7 -0
  508. package/src/components/LiquidEditor/liquidFilters.ts +23 -0
  509. package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
  510. package/src/components/LiquidEditor/types.ts +101 -0
  511. package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
  512. package/src/components/List/List.module.scss +105 -0
  513. package/src/components/List/List.tokens.scss +42 -0
  514. package/src/components/List/List.tsx +124 -0
  515. package/src/components/List/index.ts +9 -0
  516. package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
  517. package/src/components/LiveRegion/LiveRegion.tsx +116 -0
  518. package/src/components/LiveRegion/index.ts +2 -0
  519. package/src/components/Logo/Logo.module.scss +139 -0
  520. package/src/components/Logo/Logo.tokens.scss +14 -0
  521. package/src/components/Logo/Logo.tsx +126 -0
  522. package/src/components/Logo/index.ts +2 -0
  523. package/src/components/Masonry/Masonry.module.scss +42 -0
  524. package/src/components/Masonry/Masonry.tokens.scss +8 -0
  525. package/src/components/Masonry/Masonry.tsx +136 -0
  526. package/src/components/Masonry/index.ts +2 -0
  527. package/src/components/Masonry/masonryUtils.ts +42 -0
  528. package/src/components/MediaTile/MediaTile.module.scss +183 -0
  529. package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
  530. package/src/components/MediaTile/MediaTile.tsx +208 -0
  531. package/src/components/MediaTile/index.ts +8 -0
  532. package/src/components/Modal/Body.tsx +27 -0
  533. package/src/components/Modal/Close.tsx +45 -0
  534. package/src/components/Modal/Content.tsx +98 -0
  535. package/src/components/Modal/Footer.tsx +28 -0
  536. package/src/components/Modal/Header.tsx +51 -0
  537. package/src/components/Modal/Modal.module.scss +262 -0
  538. package/src/components/Modal/Modal.tokens.scss +50 -0
  539. package/src/components/Modal/Modal.tsx +23 -0
  540. package/src/components/Modal/ModalRoot.tsx +299 -0
  541. package/src/components/Modal/Overlay.tsx +101 -0
  542. package/src/components/Modal/context.ts +60 -0
  543. package/src/components/Modal/index.ts +11 -0
  544. package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
  545. package/src/components/MoneyInput/MoneyInput.tsx +433 -0
  546. package/src/components/MoneyInput/index.ts +2 -0
  547. package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
  548. package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
  549. package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
  550. package/src/components/OptionsPicker/index.ts +9 -0
  551. package/src/components/OtpInput/OtpInput.module.scss +69 -0
  552. package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
  553. package/src/components/OtpInput/OtpInput.tsx +368 -0
  554. package/src/components/OtpInput/index.ts +2 -0
  555. package/src/components/Page/Page.module.scss +30 -0
  556. package/src/components/Page/Page.tokens.scss +11 -0
  557. package/src/components/Page/Page.tsx +53 -0
  558. package/src/components/Page/index.ts +2 -0
  559. package/src/components/PageHeader/PageHeader.module.scss +197 -0
  560. package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
  561. package/src/components/PageHeader/PageHeader.tsx +310 -0
  562. package/src/components/PageHeader/index.ts +20 -0
  563. package/src/components/Pagination/Pagination.module.scss +117 -0
  564. package/src/components/Pagination/Pagination.tokens.scss +54 -0
  565. package/src/components/Pagination/Pagination.tsx +165 -0
  566. package/src/components/Pagination/index.ts +4 -0
  567. package/src/components/Pagination/paginationRange.ts +72 -0
  568. package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
  569. package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
  570. package/src/components/PasswordInput/PasswordInput.tsx +210 -0
  571. package/src/components/PasswordInput/index.ts +2 -0
  572. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
  573. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
  574. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
  575. package/src/components/PasswordStrengthMeter/index.ts +2 -0
  576. package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
  577. package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
  578. package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
  579. package/src/components/PersonDisplay/index.ts +10 -0
  580. package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
  581. package/src/components/PhoneInput/PhoneInput.tsx +271 -0
  582. package/src/components/PhoneInput/index.ts +4 -0
  583. package/src/components/PhoneInput/phone.ts +128 -0
  584. package/src/components/PillMenu/PillMenu.module.scss +117 -0
  585. package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
  586. package/src/components/PillMenu/PillMenu.tsx +324 -0
  587. package/src/components/PillMenu/index.ts +2 -0
  588. package/src/components/Popover/Anchor.tsx +37 -0
  589. package/src/components/Popover/Close.tsx +45 -0
  590. package/src/components/Popover/Content.tsx +213 -0
  591. package/src/components/Popover/Heading.tsx +33 -0
  592. package/src/components/Popover/Popover.module.scss +177 -0
  593. package/src/components/Popover/Popover.tokens.scss +22 -0
  594. package/src/components/Popover/Popover.tsx +23 -0
  595. package/src/components/Popover/PopoverRoot.tsx +75 -0
  596. package/src/components/Popover/Trigger.tsx +86 -0
  597. package/src/components/Popover/context.ts +22 -0
  598. package/src/components/Popover/index.ts +7 -0
  599. package/src/components/Progress/Progress.module.scss +110 -0
  600. package/src/components/Progress/Progress.tokens.scss +44 -0
  601. package/src/components/Progress/Progress.tsx +129 -0
  602. package/src/components/Progress/index.ts +2 -0
  603. package/src/components/QrCode/QrCode.module.scss +97 -0
  604. package/src/components/QrCode/QrCode.tokens.scss +17 -0
  605. package/src/components/QrCode/QrCode.tsx +233 -0
  606. package/src/components/QrCode/index.ts +2 -0
  607. package/src/components/QrCode/qr.ts +161 -0
  608. package/src/components/Radio/Radio.module.scss +175 -0
  609. package/src/components/Radio/Radio.tokens.scss +59 -0
  610. package/src/components/Radio/Radio.tsx +127 -0
  611. package/src/components/Radio/RadioGroup.module.scss +42 -0
  612. package/src/components/Radio/RadioGroup.tsx +120 -0
  613. package/src/components/Radio/RadioGroupContext.tsx +30 -0
  614. package/src/components/Radio/index.ts +4 -0
  615. package/src/components/Rail/Rail.module.scss +510 -0
  616. package/src/components/Rail/Rail.tokens.scss +92 -0
  617. package/src/components/Rail/Rail.tsx +287 -0
  618. package/src/components/Rail/RailCollapseToggle.tsx +57 -0
  619. package/src/components/Rail/RailFooter.tsx +17 -0
  620. package/src/components/Rail/RailGroup.tsx +728 -0
  621. package/src/components/Rail/RailGroupContext.ts +9 -0
  622. package/src/components/Rail/RailHeader.tsx +23 -0
  623. package/src/components/Rail/RailItem.tsx +119 -0
  624. package/src/components/Rail/RailSection.tsx +39 -0
  625. package/src/components/Rail/RailSpacer.tsx +19 -0
  626. package/src/components/Rail/index.ts +9 -0
  627. package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
  628. package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
  629. package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
  630. package/src/components/RelativeDateInput/index.ts +10 -0
  631. package/src/components/RelativeDateInput/relativeDate.ts +127 -0
  632. package/src/components/RichText/RichText.module.scss +5 -0
  633. package/src/components/RichText/RichText.tsx +70 -0
  634. package/src/components/RichText/RichTextAttachment.module.scss +82 -0
  635. package/src/components/RichText/RichTextAttachment.tsx +122 -0
  636. package/src/components/RichText/_prose.scss +79 -0
  637. package/src/components/RichText/attachmentIcon.tsx +24 -0
  638. package/src/components/RichText/engine/attachment.ts +154 -0
  639. package/src/components/RichText/engine/autolink.ts +64 -0
  640. package/src/components/RichText/engine/blockUnit.ts +174 -0
  641. package/src/components/RichText/engine/colorMarks.ts +85 -0
  642. package/src/components/RichText/engine/escape.ts +11 -0
  643. package/src/components/RichText/engine/fromHtml.ts +353 -0
  644. package/src/components/RichText/engine/fromMarkdown.ts +20 -0
  645. package/src/components/RichText/engine/inlines.ts +82 -0
  646. package/src/components/RichText/engine/listDepths.ts +32 -0
  647. package/src/components/RichText/engine/marks.ts +80 -0
  648. package/src/components/RichText/engine/mdToHtml.ts +178 -0
  649. package/src/components/RichText/engine/model.ts +157 -0
  650. package/src/components/RichText/engine/position.ts +118 -0
  651. package/src/components/RichText/engine/renderDoc.tsx +395 -0
  652. package/src/components/RichText/engine/renderLink.ts +15 -0
  653. package/src/components/RichText/engine/renderMention.ts +16 -0
  654. package/src/components/RichText/engine/safeHref.ts +22 -0
  655. package/src/components/RichText/engine/toHtml.ts +154 -0
  656. package/src/components/RichText/engine/toMarkdown.ts +97 -0
  657. package/src/components/RichText/engine/transforms.ts +434 -0
  658. package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
  659. package/src/components/RichText/index.ts +31 -0
  660. package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
  661. package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
  662. package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
  663. package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
  664. package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
  665. package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
  666. package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
  667. package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
  668. package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
  669. package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
  670. package/src/components/RichTextEditor/autolinkInput.ts +65 -0
  671. package/src/components/RichTextEditor/blockDrop.ts +9 -0
  672. package/src/components/RichTextEditor/blockReflow.ts +62 -0
  673. package/src/components/RichTextEditor/commands.ts +300 -0
  674. package/src/components/RichTextEditor/history.ts +93 -0
  675. package/src/components/RichTextEditor/icons.tsx +152 -0
  676. package/src/components/RichTextEditor/imageSize.ts +70 -0
  677. package/src/components/RichTextEditor/index.ts +5 -0
  678. package/src/components/RichTextEditor/input.ts +209 -0
  679. package/src/components/RichTextEditor/inputRules.ts +71 -0
  680. package/src/components/RichTextEditor/links.ts +103 -0
  681. package/src/components/RichTextEditor/mentionContext.ts +37 -0
  682. package/src/components/RichTextEditor/mentions.ts +28 -0
  683. package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
  684. package/src/components/RichTextEditor/selection.ts +415 -0
  685. package/src/components/RichTextEditor/shortcuts.ts +44 -0
  686. package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
  687. package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
  688. package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
  689. package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
  690. package/src/components/RichTextEditor/useMention.ts +226 -0
  691. package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
  692. package/src/components/RichTextEditor/useUpload.ts +246 -0
  693. package/src/components/Screen/Screen.module.scss +46 -0
  694. package/src/components/Screen/Screen.tokens.scss +20 -0
  695. package/src/components/Screen/Screen.tsx +97 -0
  696. package/src/components/Screen/index.ts +2 -0
  697. package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
  698. package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
  699. package/src/components/ScrollArea/ScrollArea.tsx +154 -0
  700. package/src/components/ScrollArea/index.ts +2 -0
  701. package/src/components/Select/Chip.tsx +45 -0
  702. package/src/components/Select/Empty.tsx +39 -0
  703. package/src/components/Select/Error.tsx +51 -0
  704. package/src/components/Select/HiddenInputs.tsx +44 -0
  705. package/src/components/Select/Listbox.tsx +557 -0
  706. package/src/components/Select/Loading.tsx +30 -0
  707. package/src/components/Select/Select.module.scss +512 -0
  708. package/src/components/Select/Select.tokens.scss +140 -0
  709. package/src/components/Select/Select.tsx +685 -0
  710. package/src/components/Select/Trigger.tsx +952 -0
  711. package/src/components/Select/context.ts +101 -0
  712. package/src/components/Select/emptyStateText.ts +19 -0
  713. package/src/components/Select/index.ts +9 -0
  714. package/src/components/Select/useSelectState.ts +157 -0
  715. package/src/components/Select/utils-types.ts +7 -0
  716. package/src/components/Select/utils.ts +122 -0
  717. package/src/components/SettingRow/SettingRow.module.scss +166 -0
  718. package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
  719. package/src/components/SettingRow/SettingRow.tsx +242 -0
  720. package/src/components/SettingRow/index.ts +7 -0
  721. package/src/components/Skeleton/Skeleton.module.scss +55 -0
  722. package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
  723. package/src/components/Skeleton/Skeleton.tsx +131 -0
  724. package/src/components/Skeleton/index.ts +4 -0
  725. package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
  726. package/src/components/Slider/Slider.module.scss +293 -0
  727. package/src/components/Slider/Slider.tokens.scss +98 -0
  728. package/src/components/Slider/Slider.tsx +624 -0
  729. package/src/components/Slider/index.ts +9 -0
  730. package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
  731. package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
  732. package/src/components/SlotGrid/SlotGrid.tsx +111 -0
  733. package/src/components/SlotGrid/index.ts +2 -0
  734. package/src/components/SocialButton/SocialButton.module.scss +4 -0
  735. package/src/components/SocialButton/SocialButton.tsx +40 -0
  736. package/src/components/SocialButton/index.ts +2 -0
  737. package/src/components/Sortable/Sortable.module.scss +177 -0
  738. package/src/components/Sortable/Sortable.tokens.scss +27 -0
  739. package/src/components/Sortable/Sortable.tsx +572 -0
  740. package/src/components/Sortable/containerAwareCollision.ts +125 -0
  741. package/src/components/Sortable/index.ts +13 -0
  742. package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
  743. package/src/components/SortableGroup/SortableGroup.tsx +315 -0
  744. package/src/components/SortableGroup/index.ts +4 -0
  745. package/src/components/SortableGroup/moveSortableItem.ts +39 -0
  746. package/src/components/Sparkline/Sparkline.module.scss +28 -0
  747. package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
  748. package/src/components/Sparkline/Sparkline.tsx +133 -0
  749. package/src/components/Sparkline/index.ts +2 -0
  750. package/src/components/Sparkline/sparklineModel.ts +119 -0
  751. package/src/components/Split/Split.module.scss +158 -0
  752. package/src/components/Split/Split.tokens.scss +10 -0
  753. package/src/components/Split/Split.tsx +231 -0
  754. package/src/components/Split/index.ts +2 -0
  755. package/src/components/Stack/Stack.module.scss +67 -0
  756. package/src/components/Stack/Stack.tokens.scss +11 -0
  757. package/src/components/Stack/Stack.tsx +100 -0
  758. package/src/components/Stack/index.ts +2 -0
  759. package/src/components/StagePath/StagePath.module.scss +255 -0
  760. package/src/components/StagePath/StagePath.tokens.scss +43 -0
  761. package/src/components/StagePath/StagePath.tsx +176 -0
  762. package/src/components/StagePath/index.ts +2 -0
  763. package/src/components/StatGroup/StatGroup.module.scss +6 -0
  764. package/src/components/StatGroup/StatGroup.tsx +70 -0
  765. package/src/components/StatGroup/StatGroupContext.ts +10 -0
  766. package/src/components/StatGroup/StatTile.module.scss +99 -0
  767. package/src/components/StatGroup/StatTile.tokens.scss +35 -0
  768. package/src/components/StatGroup/StatTile.tsx +143 -0
  769. package/src/components/StatGroup/index.ts +4 -0
  770. package/src/components/Sticky/Sticky.module.scss +98 -0
  771. package/src/components/Sticky/Sticky.tokens.scss +17 -0
  772. package/src/components/Sticky/Sticky.tsx +103 -0
  773. package/src/components/Sticky/index.ts +2 -0
  774. package/src/components/Switch/Switch.module.scss +182 -0
  775. package/src/components/Switch/Switch.tokens.scss +59 -0
  776. package/src/components/Switch/Switch.tsx +214 -0
  777. package/src/components/Switch/index.ts +2 -0
  778. package/src/components/Table/Table.module.scss +308 -0
  779. package/src/components/Table/Table.tokens.scss +79 -0
  780. package/src/components/Table/Table.tsx +381 -0
  781. package/src/components/Table/index.ts +15 -0
  782. package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
  783. package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
  784. package/src/components/TableOfContents/TableOfContents.tsx +192 -0
  785. package/src/components/TableOfContents/activeSection.ts +18 -0
  786. package/src/components/TableOfContents/index.ts +2 -0
  787. package/src/components/Tabs/Tabs.module.scss +359 -0
  788. package/src/components/Tabs/Tabs.tokens.scss +50 -0
  789. package/src/components/Tabs/Tabs.tsx +538 -0
  790. package/src/components/Tabs/index.ts +2 -0
  791. package/src/components/Text/Text.module.scss +115 -0
  792. package/src/components/Text/Text.tokens.scss +55 -0
  793. package/src/components/Text/Text.tsx +197 -0
  794. package/src/components/Text/index.ts +2 -0
  795. package/src/components/Textarea/Textarea.module.scss +94 -0
  796. package/src/components/Textarea/Textarea.tokens.scss +48 -0
  797. package/src/components/Textarea/Textarea.tsx +246 -0
  798. package/src/components/Textarea/index.ts +2 -0
  799. package/src/components/Thread/Thread.module.scss +161 -0
  800. package/src/components/Thread/Thread.tokens.scss +32 -0
  801. package/src/components/Thread/Thread.tsx +176 -0
  802. package/src/components/Thread/index.ts +2 -0
  803. package/src/components/TimeField/TimeField.module.scss +232 -0
  804. package/src/components/TimeField/TimeField.tsx +793 -0
  805. package/src/components/TimeField/index.ts +2 -0
  806. package/src/components/Timeline/Timeline.module.scss +58 -0
  807. package/src/components/Timeline/Timeline.tokens.scss +13 -0
  808. package/src/components/Timeline/Timeline.tsx +53 -0
  809. package/src/components/Timeline/index.ts +2 -0
  810. package/src/components/Title/Title.module.scss +84 -0
  811. package/src/components/Title/Title.tokens.scss +37 -0
  812. package/src/components/Title/Title.tsx +150 -0
  813. package/src/components/Title/index.ts +2 -0
  814. package/src/components/Toast/Toast.module.scss +299 -0
  815. package/src/components/Toast/Toast.tokens.scss +65 -0
  816. package/src/components/Toast/Toast.tsx +122 -0
  817. package/src/components/Toast/ToastViewport.tsx +166 -0
  818. package/src/components/Toast/api.ts +175 -0
  819. package/src/components/Toast/index.ts +5 -0
  820. package/src/components/Toast/store.ts +133 -0
  821. package/src/components/Toast/useToastTimer.ts +94 -0
  822. package/src/components/Tooltip/Tooltip.module.scss +99 -0
  823. package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
  824. package/src/components/Tooltip/Tooltip.tsx +341 -0
  825. package/src/components/Tooltip/index.ts +2 -0
  826. package/src/components/TopBar/TopBar.module.scss +235 -0
  827. package/src/components/TopBar/TopBar.tokens.scss +79 -0
  828. package/src/components/TopBar/TopBar.tsx +87 -0
  829. package/src/components/TopBar/TopBarEnd.tsx +20 -0
  830. package/src/components/TopBar/TopBarIconButton.tsx +86 -0
  831. package/src/components/TopBar/TopBarSearch.tsx +319 -0
  832. package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
  833. package/src/components/TopBar/TopBarStart.tsx +20 -0
  834. package/src/components/TopBar/index.ts +11 -0
  835. package/src/components/Tour/Spotlight.tsx +121 -0
  836. package/src/components/Tour/Tour.module.scss +210 -0
  837. package/src/components/Tour/Tour.tokens.scss +58 -0
  838. package/src/components/Tour/Tour.tsx +617 -0
  839. package/src/components/Tour/index.ts +2 -0
  840. package/src/components/Tour/useTourTarget.ts +115 -0
  841. package/src/components/TreeView/TreeView.module.scss +268 -0
  842. package/src/components/TreeView/TreeView.tokens.scss +36 -0
  843. package/src/components/TreeView/TreeView.tsx +536 -0
  844. package/src/components/TreeView/index.ts +3 -0
  845. package/src/components/TreeView/treeModel.ts +224 -0
  846. package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
  847. package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
  848. package/src/components/VisuallyHidden/index.ts +2 -0
  849. package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
  850. package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
  851. package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
  852. package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
  853. package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
  854. package/src/components/WidgetPreview/index.ts +2 -0
  855. package/src/components/_internal/Trend.tsx +27 -0
  856. package/src/components/_internal/choiceTile.scss +74 -0
  857. package/src/components/_internal/collapse.scss +10 -0
  858. package/src/components/_internal/collapse.ts +58 -0
  859. package/src/components/_internal/currency.ts +257 -0
  860. package/src/components/_internal/dragAnnouncements.ts +200 -0
  861. package/src/components/_internal/fieldWiring.ts +225 -0
  862. package/src/components/_internal/gridSpan.ts +54 -0
  863. package/src/components/_internal/isoDay.ts +35 -0
  864. package/src/components/_internal/letterKey.ts +26 -0
  865. package/src/components/_internal/overlay/focusRestore.ts +21 -0
  866. package/src/components/_internal/overlay/index.ts +12 -0
  867. package/src/components/_internal/overlay/tourHold.ts +23 -0
  868. package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
  869. package/src/components/_internal/overlay/useInOverlay.ts +81 -0
  870. package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
  871. package/src/components/_internal/overlay/useScrollLock.ts +112 -0
  872. package/src/components/_internal/refs.ts +48 -0
  873. package/src/components/_internal/statusColor.ts +26 -0
  874. package/src/components/_internal/timeUtils.ts +23 -0
  875. package/src/components/_internal/useAsyncOptions.ts +145 -0
  876. package/src/components/_internal/useClippedTooltip.ts +50 -0
  877. package/src/components/_internal/useControllableState.ts +50 -0
  878. package/src/components.manifest.json +1141 -0
  879. package/src/hooks/useBelowBreakpoint.ts +58 -0
  880. package/src/i18n/I18nProvider.tsx +52 -0
  881. package/src/i18n/LocaleProvider.tsx +17 -0
  882. package/src/i18n/en.ts +648 -0
  883. package/src/i18n/format.ts +71 -0
  884. package/src/i18n/index.ts +13 -0
  885. package/src/i18n/messages.ts +1275 -0
  886. package/src/i18n/ru.ts +677 -0
  887. package/src/i18n/useLocale.ts +19 -0
  888. package/src/i18n/useTranslation.ts +58 -0
  889. package/src/index.ts +913 -0
  890. package/src/palette/index.ts +2 -0
  891. package/src/palette/palette.ts +108 -0
  892. package/src/styles/dark.scss +4 -0
  893. package/src/styles/global.scss +7 -0
  894. package/src/styles/mixins.scss +143 -0
  895. package/src/styles/reset.scss +78 -0
  896. package/src/styles/tokens.scss +18 -0
  897. package/src/styles/typography.scss +44 -0
@@ -0,0 +1,214 @@
1
+ # `<TopBar>` — sticky application top bar
2
+
3
+ Horizontal app-chrome bar pinned to the top of the viewport. Compound API: `<TopBar.Start>` + `<TopBar.End>` for the two horizontal clusters, plus `<TopBar.Search>` (styled `<input type="search">` with a leading icon and an optional `<kbd>` hotkey hint) and `<TopBar.IconButton>` (icon-only ghost button with an optional notification-dot indicator).
4
+
5
+ ```tsx
6
+ import { Avatar, TopBar } from '@eocrm/design-system';
7
+ import { Bell, Plus } from 'lucide-react';
8
+
9
+ <TopBar>
10
+ <TopBar.Start>
11
+ <TopBar.Search placeholder="Search contacts, deals…" hotkey="⌘K" />
12
+ </TopBar.Start>
13
+ <TopBar.End>
14
+ <TopBar.IconButton aria-label="Create new">
15
+ <Plus size={16} />
16
+ </TopBar.IconButton>
17
+ <TopBar.IconButton aria-label="Notifications, 3 unread" indicator>
18
+ <Bell size={16} />
19
+ </TopBar.IconButton>
20
+ <Avatar name="Alex Rivera" size="sm" />
21
+ </TopBar.End>
22
+ </TopBar>;
23
+ ```
24
+
25
+ <!-- props:start -->
26
+
27
+ ## Props
28
+
29
+ ### `TopBarProps`
30
+
31
+ <!-- prettier-ignore -->
32
+ | Prop | Type | Required | Description |
33
+ |---|---|---|---|
34
+ | `as` | `'header' \| 'div'` | no | Element to render. Defaults to `'header'`. Pick `'div'` when the bar is nested inside another content area where a second `<header>` landmark would conflict with page semantics. |
35
+ | `aria-label` | `string` | no | Accessible label for the bar's landmark. Defaults to `t('topBar.label')` when omitted OR empty — an empty string is not an explicit name — so screen readers always announce a name for the region. Override when a page has multiple bars to disambiguate them. |
36
+ | `children` | `ReactNode` | no | Children of the bar — typically `<TopBar.Start>` + `<TopBar.End>`. The children area is open so consumers can render a single cluster, a single trailing element, or any other arrangement they need. |
37
+ | …native | | | plus native HTML attributes |
38
+
39
+ ### `TopBarEndProps`
40
+
41
+ <!-- prettier-ignore -->
42
+ | Prop | Type | Required | Description |
43
+ |---|---|---|---|
44
+ | …native | | | plus native `<div>` attributes |
45
+
46
+ ### `TopBarIconButtonProps`
47
+
48
+ <!-- prettier-ignore -->
49
+ | Prop | Type | Required | Description |
50
+ |---|---|---|---|
51
+ | `children` | `ReactNode` | yes | Icon to render inside the button. Typically a single lucide icon (e.g. `<Bell size={16} />`). The wrapping button supplies the accessible name via `aria-label` — the icon itself is decorative. |
52
+ | `indicator` | `boolean` | no | Show a small dot in the upper-right corner of the button. Useful for "unread notifications", "pending updates", etc. The dot is purely visual (`aria-hidden`); the consumer is responsible for surfacing count / status text to assistive tech, typically via the button's `aria-label` or a hidden span. |
53
+ | `indicatorTone` | `'danger' \| 'warning' \| 'info' \| 'accent'` | no | Dot color. Defaults to `'danger'` (red). See `TopBarIndicatorTone` for the full option set. |
54
+ | `aria-label` | `string` | yes | **Required.** Accessible name for the icon-only button — without it, screen readers announce nothing. Phrase as an action (`'Notifications'`, `'Create new'`). Include count info here when the indicator is on (e.g. `'Notifications, 3 unread'`). |
55
+ | …native | | | plus native `<button>` attributes |
56
+
57
+ ### `TopBarSearchProps`
58
+
59
+ <!-- prettier-ignore -->
60
+ | Prop | Type | Required | Description |
61
+ |---|---|---|---|
62
+ | `hotkey` | `string \| string[]` | no | Optional hotkey hint shown after the input. Rendered internally via `<Kbd size="sm">`. Pass an **array** of key labels for a multi-key combo (`['⌘', 'K']` → two chips joined with `+`) or a single string for a one-chip hint (`'Esc'` → one chip). Note: `'⌘K'` is treated as a single chip — use the array form for multi-key combos. The hint is **visual only**; the library does not bind any keyboard shortcut to it. Omit for no hint. |
63
+ | `className` | `string` | no | `className` for the wrapping `<div>` (the search surface itself). The input's own className lives on the underlying `<input>` via the spread input-props (use the standard `inputClassName` pattern if you need to target the inner element specifically — not exposed in v1). |
64
+ | `results` | `TopBarSearchGroup[]` | no | Turns on combobox mode: the input gets `role="combobox"` and a results panel opens under it. Presence switches the mode — pass `[]` (not `undefined`) while there are no results yet. You filter or fetch; the library owns keyboard, focus, dismissal, positioning and announcements. The first row is highlighted whenever the set of ids changes, so Enter opens the top hit. |
65
+ | `open` | `boolean` | no | Controlled panel visibility. Omit for uncontrolled. |
66
+ | `defaultOpen` | `boolean` | no | Uncontrolled initial visibility. Default `false`. |
67
+ | `onOpenChange` | `((open: boolean) => void)` | no | Called when the panel wants to open (focus, typing, ↓) or close (Esc, blur, selection). |
68
+ | `onSelect` | `((item: TopBarSearchItem, groupIndex: number) => void)` | no | Called on Enter or click on a result. The input text is left as is — clear it here if wanted. |
69
+ | `loading` | `boolean` | no | Shows a loading row and sets `aria-busy`; existing results stay visible and the live region keeps announcing their count. |
70
+ | `emptyMessage` | `ReactNode` | no | Row shown for a non-empty query with no results. Default `t('topBar.searchEmpty')` (also used when this is an empty string). A non-string node is rendered but the live region still announces the default text — pass a string to have it announced. |
71
+ | `footerAction` | `TopBarSearchFooterAction` | no | Trailing row in the ↑/↓ cycle (e.g. "View all results"). Rendered whenever the panel is shown (results, loading row, or empty row), as the last row. |
72
+ | …native | | | plus native `<input>` attributes |
73
+
74
+ ### `TopBarStartProps`
75
+
76
+ <!-- prettier-ignore -->
77
+ | Prop | Type | Required | Description |
78
+ |---|---|---|---|
79
+ | …native | | | plus native `<div>` attributes |
80
+
81
+ <!-- props:end -->
82
+
83
+ - **Compound API** — `TopBar.Start` / `TopBar.End` / `TopBar.Search` / `TopBar.IconButton`.
84
+ - **Layout-owning primitive (Hard rule 4 exception)** — like `<Modal>`, `<Drawer>`, `<Page>`, `<Rail>`, the bar owns its own height (56px), sticky positioning, padding, background, and bottom border because that IS its job as a top-bar chrome.
85
+ - **`<TopBar.Start>`** — flex-grows (`flex: 1`) so a sibling `<TopBar.End>` is pushed to the right edge with no spacer needed.
86
+ - **`<TopBar.End>`** — shrinks to its content. Use for trailing actions + avatar.
87
+ - **`<TopBar.Search>`** — a real `<input type="search">` (browsers expose `role="searchbox"`). `placeholder` is consumer-controlled. `aria-label` defaults to the placeholder, then to `t('topBar.search')`. The `hotkey` prop renders a trailing `<kbd>` hint — purely **visual**; binding ⌘K to focus is the consumer's responsibility. Spread `value` / `onChange` through normally — they reach the underlying input. The component sets `autoComplete="off"` plus `data-1p-ignore` / `data-lpignore` / `data-form-type="other"` so password managers and browser autofill skip it.
88
+ - **i18n**: `topBar.label` (default `<header>` aria-label), `topBar.search` (default `<input>` aria-label fallback), `topBar.searchEmpty` (default empty-results row), `topBar.searchLoading` (loading row + announcement), `topBar.searchResults` (result-count announcement).
89
+ - **Type note**: `TopBarSearchProps` omits the native `onSelect` (text-selection event) and the legacy `results` input attribute in favour of the combobox props below.
90
+
91
+ ### Combobox mode (`results`)
92
+
93
+ Passing `results` (even `[]`) turns the pill into an ARIA combobox with a results panel. You filter or fetch; the library owns keyboard, focus, dismissal, positioning and announcements.
94
+
95
+ ```tsx
96
+ const [q, setQ] = useState('');
97
+ const { data, isFetching } = useSearch(q); // your fetch; returns TopBarSearchGroup[]
98
+ // If you debounce, set `loading` synchronously in onChange (see below) instead of waiting for isFetching.
99
+
100
+ <TopBar.Search
101
+ placeholder="Search contacts, deals…"
102
+ hotkey={['⌘', 'K']}
103
+ value={q}
104
+ onChange={(e) => setQ(e.target.value)}
105
+ results={data ?? []}
106
+ loading={isFetching}
107
+ onSelect={(item) => navigate(item.href ?? `/records/${item.id}`)}
108
+ footerAction={
109
+ q
110
+ ? {
111
+ label: `View all results for “${q}”`,
112
+ onSelect: () => navigate(`/search?q=${encodeURIComponent(q)}`),
113
+ }
114
+ : undefined
115
+ }
116
+ />;
117
+ // data: [{ label: 'Contacts', items: [{ id: 'c1', label: 'Ada Lovelace', meta: 'Contact', href: '/contacts/c1' }] }]
118
+ ```
119
+
120
+ - The first row is highlighted every time the set of ids changes (so Enter opens the top hit); rebuilding `results` inline with the same ids keeps the highlight.
121
+ - ↑ / ↓ move the highlight and wrap, including the `footerAction` row.
122
+ - Enter or click calls `onSelect(item, groupIndex)`, closes the panel and keeps the input text (clear it in `onSelect` if wanted). A `footerAction` row calls its own `onSelect`.
123
+ - Esc closes the panel (innermost overlay first) and does not clear the input; blur closes it.
124
+ - Rows with `href` render as links: Cmd/Ctrl/Shift/middle-click and "copy link" work natively; a plain click or Enter still calls `onSelect` (the library prevents the default navigation).
125
+ - The panel is at least as wide as the pill, height-capped, and scrolls itself — do not wrap results in `<ScrollArea>`.
126
+ - The panel shows only for a non-empty query, a loading state, or when there are results. `loading` keeps existing results visible and sets `aria-busy`.
127
+ - Result count, loading and empty states are announced via a live region. If `emptyMessage` is a non-string node, the live region announces the default `topBar.searchEmpty` instead — pass a string to have it announced. An empty-string `emptyMessage` falls back to the default.
128
+ - Groups with no items are not rendered, so you may pass them as-is.
129
+ - **Debounced fetch**: set `loading` to `true` synchronously in your `onChange`, independent of the debounced request. Otherwise the panel shows and announces "No results" for the new query until the fetch actually starts.
130
+ - Enter or click while `loading` acts on the currently shown (previous) results.
131
+ - In uncontrolled mode the "empty query" check follows typing (`onChange`). After a form reset or an imperative `.value =` write, use a controlled `value`.
132
+ - `open` / `defaultOpen` / `onOpenChange` control visibility if you need to; omit for uncontrolled. With `defaultOpen` or a controlled `open` and the input never focused, the panel closes only via Esc, selection, or your `open` prop — there is no outside-click listener; outside-click dismissal comes from the input's blur.
133
+ - Hide `footerAction` (pass `undefined`) while the query is empty — "View all results for “”" is noise.
134
+
135
+ #### Shapes
136
+
137
+ `TopBarSearchGroup` — one labelled block in `results`. Groups with no items are not rendered.
138
+
139
+ <!-- prettier-ignore -->
140
+ | Field | Type | Required | Description |
141
+ |---|---|---|---|
142
+ | `label` | `string` | yes | Visible heading; also the group's accessible name. |
143
+ | `items` | `TopBarSearchItem[]` | yes | Result rows in this group. |
144
+
145
+ `TopBarSearchItem` — one result row.
146
+
147
+ <!-- prettier-ignore -->
148
+ | Field | Type | Required | Description |
149
+ |---|---|---|---|
150
+ | `id` | `string` | yes | Unique across ALL groups. Identifies the result set: the highlight resets to the first row when the set of ids changes. |
151
+ | `label` | `ReactNode` | yes | Primary text. Truncates to one line. |
152
+ | `meta` | `ReactNode` | no | Trailing muted text, e.g. the entity type or an email. |
153
+ | `icon` | `ReactNode` | no | Leading decorative icon (e.g. `<User size={16} />`); hidden from assistive tech. |
154
+ | `href` | `string` | no | Renders the row as a link so Cmd/Ctrl/Shift/middle-click and "copy link" work natively. A plain click or Enter still calls `onSelect` (the library never navigates). |
155
+
156
+ `TopBarSearchFooterAction` — the optional `footerAction`. It renders whenever the panel is shown (results, the loading row, or the empty row for a non-empty query), as the last row in the ↑/↓ cycle.
157
+
158
+ <!-- prettier-ignore -->
159
+ | Field | Type | Required | Description |
160
+ |---|---|---|---|
161
+ | `label` | `ReactNode` | yes | Row content. |
162
+ | `onSelect` | `() => void` | yes | Called on Enter or click. |
163
+ | `href` | `string` | no | Optional link target, same semantics as `TopBarSearchItem.href`. |
164
+
165
+ #### When NOT to use
166
+
167
+ - ❌ Picking a form value from a list — use `<Select>`.
168
+ - ❌ Filter chips / multi-select facets — use `<OptionsPicker>`.
169
+ - ❌ A command palette in a modal — not covered by combobox mode.
170
+ - ❌ Left-side navigation column — use `<Rail>`.
171
+ - ❌ Page-local heading + actions — use `<PageHeader>`, not a TopBar.
172
+ - ❌ Action toolbar attached to a specific section — use a `<Cluster>` inside that section; TopBar is for the application's top chrome.
173
+ - ❌ Wrapping `<TopBar.Search>` in `<Popover>` to show results — use combobox mode (`results`).
174
+
175
+ #### Anti-patterns
176
+
177
+ - ❌ Wrapping the bar in another `position: sticky` container — the bar already sticks. Layered sticky parents stack at the wrong offset.
178
+ - ❌ Reaching for `<TopBar.IconButton>` outside the bar — it's a topbar-scoped size + indicator pattern. Use `<Button iconOnly variant="ghost">` for general icon buttons.
179
+ - ❌ Putting a `<Button variant="primary">` inside the bar — primary actions belong in the page body where they're discoverable; the topbar is for navigation, search, and global ambient actions only.
180
+ - ❌ Keying or remounting `<TopBar.Search>` as results arrive — the input is never remounted by changing `results`, so don't add a `key` that does. Pass `[]` (not `undefined`) while there are no results: `undefined` turns combobox mode off (no role, no panel).
181
+ - ❌ Duplicate `id`s across groups — ids must be unique across ALL groups (they identify the result set for highlight reset).
182
+ - ❌ Clearing the input inside `onChange` — it fights typing; clear in `onSelect` if you want that.
183
+ - ❌ Navigating in both `onSelect` and via the `<a>` default — the library already prevents the default on plain clicks; route only in `onSelect`.
184
+ - ❌ Relying on the indicator dot to communicate count to assistive tech — the dot is decorative (`aria-hidden`); put the count in the `aria-label` instead.
185
+
186
+ ```tsx
187
+ // Right-aligned actions only — Start can be omitted; End still sits right.
188
+ <TopBar>
189
+ <TopBar.End>
190
+ <TopBar.IconButton aria-label="Settings"><Settings size={16} /></TopBar.IconButton>
191
+ </TopBar.End>
192
+ </TopBar>
193
+
194
+ // Nested secondary toolbar — as="div" avoids stacking two <header> landmarks:
195
+ <TopBar as="div" aria-label="Filters">
196
+ <TopBar.Start>…</TopBar.Start>
197
+ </TopBar>
198
+
199
+ // Search hotkey hint — array form renders one chip per key; string form one chip:
200
+ <TopBar.Search placeholder="Search contacts, deals…" hotkey={['⌘', 'K']} />
201
+ <TopBar.Search placeholder="Filter…" hotkey="/" />
202
+
203
+ // Soft-cue indicator tone:
204
+ <TopBar.IconButton aria-label="Maintenance scheduled" indicator indicatorTone="warning">
205
+ <Wrench size={16} />
206
+ </TopBar.IconButton>
207
+ ```
208
+
209
+ - `<TopBar.Start>` typically holds a brand mark, workspace switcher and/or `<TopBar.Search>`; `<TopBar.End>` trailing `<TopBar.IconButton>`s and the user `<Avatar>`.
210
+ - `<TopBar.Search>` is a 32px pill with a leading search icon; the native `type="search"` gives `role="searchbox"` and the browser's clear button. It has no keyboard-shortcut behaviour of its own.
211
+ - `<TopBar.IconButton>` is icon-only (the 32×32 size and `indicator` dot are bar-specific); for a labelled action use a regular `<Button>`.
212
+ - ❌ A submit button inside the search wrapper: read the value from `onKeyDown` / `onChange` on Enter.
213
+ - ❌ `placeholder` and `aria-label` set to different strings: the default aria-label IS the placeholder; override only when the placeholder is too terse alone.
214
+ - ❌ A search field in a form: use `<Input>`; the pill styling is specific to the bar.
@@ -0,0 +1,85 @@
1
+ # `<Tour>` — guided tour / onboarding walkthrough
2
+
3
+ ```tsx
4
+ <Button data-tour="bulk-edit">Bulk edit</Button>
5
+
6
+ <Tour
7
+ open={open}
8
+ onOpenChange={setOpen}
9
+ onFinish={(reason) => markSeen('bulk-edit', reason)}
10
+ steps={[
11
+ { title: 'Welcome', body: 'A quick look around.' },
12
+ { target: 'bulk-edit', title: 'Bulk edit', body: 'Select rows, then edit them together.' },
13
+ ]}
14
+ />
15
+ ```
16
+
17
+ **Removed tokens:** `--tour-pulse-color`, `--tour-pulse-width`, `--tour-pulse-spread` and `--tour-pulse-duration` are replaced by the `--tour-wave-*` tokens. `--tour-waiting-opacity` was removed (the waiting card stays opaque).
18
+
19
+ <!-- props:start -->
20
+
21
+ ## Props
22
+
23
+ <!-- prettier-ignore -->
24
+ | Prop | Type | Required | Description |
25
+ |---|---|---|---|
26
+ | `steps` | `TourStep[]` | yes | The steps, in order. Must be non-empty. |
27
+ | `open` | `boolean` | yes | Controlled open state (required — like `Modal`, there is no uncontrolled mode: an uncontrolled tour could not be started or replayed). |
28
+ | `onOpenChange` | `(open: boolean) => void` | yes | Called with `false` on Skip, Escape and Done. |
29
+ | `onFinish` | `((reason: TourFinishReason) => void)` | no | Fires once per Skip / Escape / Done. NOT called when the consumer closes the tour itself by setting `open={false}` — only the tour's own end gestures fire it. Use it to persist "seen" state. |
30
+ | `step` | `number` | no | Controlled step index. Control it when a step change must do something first — navigate to another page, open an accordion, switch a tab — then the Tour waits for the next target to mount. |
31
+ | `onStepChange` | `((index: number) => void)` | no | Fires on every step change (Next, Back, arrow keys, `advanceOn`), controlled or not. |
32
+ | `defaultStep` | `number` | no | Uncontrolled starting step. Default `0`. Every re-open starts here again. |
33
+ | `modal` | `boolean` | no | `true` (default): dims the page with a spotlight cutout, blocks clicks outside it and traps focus — onboarding. `false`: card only, page stays usable — feature announcements. |
34
+ | `targetTimeout` | `number` | no | Ms to wait for a step's target before falling back to a centered card. Default `5000` (room for a route change + data fetch). `Infinity` waits forever. |
35
+ | `onTargetMissing` | `((step: TourStep, index: number) => void)` | no | Called when a step's target didn't appear within `targetTimeout`. Log it. |
36
+ | `doneLabel` | `string` | no | Contextual label for the last step's button, e.g. `'Got it'` for a one-step announcement. Defaults to the i18n `tour.done` (`'Done'`). An empty string counts as unset. |
37
+ | …native | | | plus native `<div>` attributes |
38
+
39
+ <!-- props:end -->
40
+
41
+ - **Targets are `data-tour` values**, not selectors or refs: put `data-tour="x"` on the element, `target: 'x'` on the step. No `target` → centered step.
42
+ - **Pointing into a menu:** a step can target an open `DropdownMenu`/`Popover`/`Select` panel or an item inside it. Pressing Next/Back or focusing the card doesn't close the surface, and it drops just under the scrim so only the target is lit, not the whole panel (when the step targets the panel itself, the whole panel stays above the scrim). Make the preceding step `interactive` + `advanceOn: 'click'` on the trigger so the user opens it themselves. On a non-interactive step a lifted panel is lit but not clickable (`data-tour-inert` blocks pointer events; it stays visible to assistive tech, and keyboard is held by the card's focus trap). For the same reason a lifted panel on a non-interactive step doesn't scroll by wheel: it's intended (look, don't touch).
43
+ - **Known limit:** a step pointing into a nested surface (a `DropdownMenu` submenu, a `Popover` inside a `Popover`, the `DatePicker` clock) holds only that inner surface, so pressing Next/Back can still close its parent.
44
+ - **Cross-page tours:** mount `<Tour>` once in the app shell, control `step`, navigate inside `onStepChange`. The Tour waits for the next target (`targetTimeout`, default 5000ms, `Infinity` = forever), then falls back to a centered card and calls `onTargetMissing`.
45
+ - **"Click it to continue":** `{ interactive: true, advanceOn: 'click' }` — target stays clickable and joins the focus trap; the tour advances after its click handler runs. The card's Next (or Done) performs that click on the target (full pointer sequence), so the step's action still happens; Next never skips it unless the step sets `next: 'skip'` (below). The card shows a "Click the highlighted element to continue" hint (`tour.clickHint`) and demotes Next to `secondary` so the target reads as the primary action; in modal mode, waves grow outward from the spotlight edge (a static ring under reduced motion). Same hint + secondary Next with `modal={false}` (no spotlight there). Add `next: 'skip'` (default `'click'`) when the target's action has side effects Next shouldn't trigger: Next/Done then advance with `goNext()` without clicking the target (ArrowRight does the same but does nothing on the last step; only Done finishes), while a real click still advances — e.g. `{ target: 'delete-btn', title: 'Delete', interactive: true, advanceOn: 'click', next: 'skip' }`.
46
+ - Strings (`Next`, `Back`, `Skip tour`, `Done`, `Step n of m`, the click hint) come from i18n `tour.*`; only `doneLabel` is a prop.
47
+
48
+ **Anti-patterns:**
49
+
50
+ - ❌ `target: '#bulk-edit'` — it's the `data-tour` value, not a selector.
51
+ - ❌ Mounting a cross-page `<Tour>` inside a routed page — it unmounts on navigation.
52
+ - ❌ `advanceOn: 'click'` without `interactive: true` in modal mode — the target is blocked.
53
+ - ❌ Auto-opening every visit — gate on your own seen flag.
54
+ - ❌ An `interactive: true` modal step whose target opens a `Modal`/`Drawer` — it
55
+ renders beneath the tour's scrim. End the step first (`advanceOn: 'click'`,
56
+ point the next step into the opened Modal/Drawer) or use `modal={false}`.
57
+ Library floating surfaces (menus, popovers, selects) opened from an
58
+ interactive target elevate above the tour automatically.
59
+
60
+ ```tsx
61
+ // One-step feature announcement — page stays usable:
62
+ <Tour open={open} onOpenChange={setOpen} modal={false} doneLabel="Got it"
63
+ steps={[{ target: 'bulk-edit', title: 'New: bulk edit', body: 'Select rows, then edit them together.' }]} />
64
+
65
+ // Cross-page: controlled step, navigate first, Tour waits for the target.
66
+ // Symmetric on i, not a one-shot `i === 3`: Back past step 3 must navigate away too.
67
+ <Tour open={open} onOpenChange={setOpen} step={step}
68
+ onStepChange={(i) => { navigate(i >= 3 ? '/contacts' : '/deals'); setStep(i); }}
69
+ steps={steps} />
70
+ ```
71
+
72
+ - Each step spotlights its `data-tour` target and anchors a card (title, body, "Step n of m", Skip / Back / Next) to it. Steps without a target, or whose target never appears, render as a centered card. Every transition animates; all motion drops under `prefers-reduced-motion`.
73
+ - **Keyboard:** Escape skips; ←/→ move between steps (not inside inputs).
74
+
75
+ **When NOT to use**
76
+
77
+ - A single contextual hint on hover/focus: `<Tooltip>`.
78
+ - An interactive panel the user opens themselves: `<Popover>`.
79
+ - A blocking decision: `<Modal>` / `<ConfirmationPopover>`.
80
+ - Persistent inline guidance: `<Alert>` or `EmptyState`.
81
+
82
+ **More anti-patterns**
83
+
84
+ - ❌ Two elements with the same `data-tour` value on screen: the first rendered wins (dev warning). Keep ids unique per screen.
85
+ - ❌ 10+ step tours: keep onboarding to about 5-7 steps; split longer ones per page.
@@ -0,0 +1,113 @@
1
+ # `<TreeView>` — lazily loaded hierarchy, as a file list or an org chart
2
+
3
+ TL;DR: a WAI-ARIA tree for hierarchies the app loads level by level (organization units, folders, categories). Two views of the same data: `list` (file-explorer rows) and `chart` (classic top-down org chart). The app owns fetching, caching and errors; TreeView owns rendering, keyboard, focus, selection and the loading / error / "N more" rows.
4
+
5
+ ```tsx
6
+ import { TreeView, type TreeViewNode } from '@eocrm/design-system';
7
+
8
+ const [expanded, setExpanded] = useState<Set<string>>(() => new Set());
9
+ const children = useQueries({ queries: [...expanded].map((id) => unitsQuery({ parent: id })) });
10
+ const byId = new Map([...expanded].map((id, i) => [id, children[i]]));
11
+
12
+ <TreeView
13
+ aria-label="Organization structure"
14
+ view="list" // or "chart"
15
+ roots={roots.map(toNode)}
16
+ childrenOf={(id) => {
17
+ const q = byId.get(id);
18
+ // No data yet: failed (and not retrying) → error row, otherwise → loading row.
19
+ if (!q?.data) return q?.isError && !q.isFetching ? { error: true } : undefined;
20
+ return q.data.units.map(toNode); // loaded data stays even if a background refetch fails
21
+ }}
22
+ expandedIds={expanded}
23
+ onExpandedChange={(id, open) =>
24
+ setExpanded((prev) => {
25
+ const next = new Set(prev);
26
+ if (open) next.add(id);
27
+ else next.delete(id);
28
+ return next;
29
+ })
30
+ }
31
+ selectedId={selectedId}
32
+ onSelect={openDrawer}
33
+ onRetry={(id) => byId.get(id)?.refetch()}
34
+ overflowOf={(parentId) =>
35
+ hiddenCount(parentId) > 0 ? { label: t('more', { count: hiddenCount(parentId) }) } : null
36
+ }
37
+ />;
38
+ ```
39
+
40
+ <!-- props:start -->
41
+
42
+ ## Props
43
+
44
+ <!-- prettier-ignore -->
45
+ | Prop | Type | Required | Description |
46
+ |---|---|---|---|
47
+ | `aria-label` | `string` | yes | Accessible name of the tree, e.g. "Organization structure". Required. |
48
+ | `view` | `'list' \| 'chart'` | no | Presentation. Default `'list'`. - `'list'` — file-explorer rows indented per level with a chevron; ↑/↓ walk rows, →/← expand/collapse. - `'chart'` — classic top-down org chart of boxes with connector lines; scrolls horizontally inside itself when wider than its container. Spatial keys: ↓ expands or enters, ↑ collapses or goes to the parent, ←/→ between siblings. |
49
+ | `roots` | `TreeViewNode[]` | yes | Top-level nodes. |
50
+ | `childrenOf` | `(id: string) => TreeViewChildren` | yes | Children of an expanded node: the array once loaded, `undefined` while loading, `{ error: true }` on failure. Called only for expanded nodes. |
51
+ | `expandedIds` | `ReadonlySet<string>` | yes | Ids of expanded nodes (controlled). Fetch a node's children when it appears here. |
52
+ | `onExpandedChange` | `(id: string, expanded: boolean) => void` | yes | Called when the user expands or collapses a node. |
53
+ | `selectedId` | `string \| null` | no | Selected node id (controlled). Ignored when `onSelect` is absent. |
54
+ | `onSelect` | `((id: string) => void)` | no | Called on click / Enter / Space on a node. Omit for a tree without selection (no `aria-selected`). Selection never follows focus. |
55
+ | `onRetry` | `((id: string) => void)` | no | Makes a failed level's "Couldn't load. Retry" row actionable; called with the parent id. Without it the row is inert text. |
56
+ | `overflowOf` | `((parentId: string \| null) => TreeViewOverflow \| null)` | no | "N more not shown" row at the end of a level (`parentId` `null` = root level), or `null` for none. Pass `onLoadMore` to make it actionable. |
57
+ | `highlightedIds` | `ReadonlySet<string>` | no | Ids to paint as a path, e.g. the selected node's ancestor ids plus its own id (TreeView cannot derive ancestors: `childrenOf` is only called for expanded nodes). Visual only — no ARIA, no effect on selection or focus. Ids not rendered are ignored. List view: accent edge on the rows; chart view: accent boxes and the connector lines between highlighted parents and children. |
58
+ | `onHoverChange` | `((id: string \| null) => void)` | no | Pointer entered/left a node's row (list) or box (chart); `null` on leave. Pointer only — no ARIA, focus or selection effect. Pair with `highlightedIds` to paint a hover chain. |
59
+ | …native | | | plus native `<div>` attributes |
60
+
61
+ <!-- props:end -->
62
+
63
+ - **Nodes.** `TreeViewNode = { id: string; label: string; hasChildren: boolean; content?: ReactNode }`. `hasChildren` drives the chevron / toggle and `aria-expanded` even before the children load; `label` is the accessible name and the typeahead text.
64
+ - **Lazy by contract.** `childrenOf(id)` is called only for expanded nodes: return the array once loaded, `undefined` while loading, including a query that is pending but not fetching (a "Loading…" row), `{ error: true }` on failure (a "Couldn't load. Retry" row; actionable only with `onRetry`). `childrenOf` must also return `undefined` while a retry is in flight (react-query v5 keeps `isError` true while refetching after an error: return the error only when there is no data and nothing is fetching), otherwise there is no loading row and a second failure is silent. Start the fetch when an id appears in `expandedIds`. A tree already in memory is fine too: return arrays immediately, don't fake loading.
65
+ - **Controlled.** `expandedIds` / `onExpandedChange` and `selectedId` / `onSelect` are controlled. Omit `onSelect` for a tree without selection. Selection never follows focus: arrows move, Enter / Space / click select.
66
+ - **Overflow.** `overflowOf(parentId)` (`null` = root level) returns `{ label, onLoadMore?, loading? }` (or `null`) and adds a muted "N more not shown" row at the end of a level. `onLoadMore` makes it actionable, `loading` marks the fetch in flight; focus then moves to the first new item (if nothing new arrives it stays on the overflow row).
67
+ - **Rows** are named by `label`; `content` is visual only and must not contain buttons, links or inputs (a treeitem's content is not separately reachable). Put actions in the selection target (a drawer, a detail pane).
68
+ - **Keyboard — list:** ↑/↓ move, → expands or enters, ← collapses or goes to the parent, Home/End, Enter/Space select, type to jump (the typeahead buffer resets after 500ms). **Chart:** ↓ expands or enters, ↑ collapses or goes to the parent, ←/→ move between siblings; the tree describes these keys to screen readers (merged with your own `aria-describedby`).
69
+ - **Screen readers:** one tab stop; levels, positions and expanded state come from ARIA. A slow (≥ 300ms) user-triggered load is announced once ("Loading…"), a failure is announced; success is silent. After Retry focus stays on the status row while loading and moves to the first child when children arrive (if the retry fails again it stays on the Retry row).
70
+ - **Empty tree.** An empty tree is not useful and not valid ARIA (a `tree` needs items): until roots load render a `Skeleton`, `EmptyState` or `ErrorState` instead of `<TreeView roots={[]}>`. A node whose loaded children are `[]` renders no group.
71
+ - **Highlighted path.** Pass `highlightedIds` the selected unit's ancestor ids plus its own id to paint the reporting line: list rows get an accent inline-start edge; chart boxes, and the connectors between a highlighted parent and its highlighted children, turn accent. TreeView cannot derive ancestors itself (`childrenOf` is only called for expanded nodes), so build the set from your data's parent map. Ids not rendered are ignored.
72
+
73
+ ```tsx
74
+ <TreeView
75
+ view="chart"
76
+ selectedId={selected}
77
+ onSelect={setSelected}
78
+ highlightedIds={pathTo(selected)} // selected id + its ancestor ids, from your parent map
79
+ {...rest}
80
+ />
81
+ ```
82
+
83
+ - **Hover.** `onHoverChange(id | null)` fires when the pointer enters or leaves a node's whole row (list) or box (chart); `null` on leave. Status rows (loading / error / overflow) don't fire; pointer only, with no effect on focus, selection or ARIA. Pair it with `highlightedIds` to paint the hovered node's chain. If the hovered node unmounts (collapsed or removed) no `null` is emitted, so clear your hover state when you collapse or remove nodes.
84
+
85
+ ```tsx
86
+ const [hovered, setHovered] = useState<string | null>(null);
87
+
88
+ <TreeView
89
+ onHoverChange={setHovered}
90
+ highlightedIds={pathTo(hovered)} // hovered id + its ancestor ids, from your parent map
91
+ onExpandedChange={(id, open) => {
92
+ toggle(id, open);
93
+ setHovered(null); // the hovered node may have just unmounted
94
+ }}
95
+ {...rest}
96
+ />;
97
+ ```
98
+
99
+ - **Sizing.** `list` grows with its content — put it in a scrolling parent for long trees. `chart` fills its parent's width and scrolls horizontally inside itself when the chart is wider; it opens centred on the selected (or first) item (when the view is chosen or the first items appear), and the focused box scrolls into view.
100
+
101
+ #### When NOT to use
102
+
103
+ - ❌ App navigation → `Rail` (with `Rail.Group`).
104
+ - ❌ A flat or two-level list → `Card.List`, `Table`, `Accordion`.
105
+ - ❌ Multi-select / checkbox trees, drag-and-drop reordering — not supported.
106
+
107
+ #### Anti-patterns
108
+
109
+ - ❌ Buttons, links or menus inside `content`.
110
+ - ❌ Returning `undefined` forever on a failed fetch — return `{ error: true }`.
111
+ - ❌ Selecting on focus (opening a drawer on every arrow key).
112
+ - ❌ Using `highlightedIds` as selection — it is visual only and sets no ARIA; keep `selectedId` for the selected node.
113
+ - ❌ Wrapping the chart view in a fixed-width scroller — it scrolls itself.
@@ -0,0 +1,43 @@
1
+ # `<VisuallyHidden>` — content for assistive tech only
2
+
3
+ ```tsx
4
+ <VisuallyHidden>Opens in a new tab</VisuallyHidden>
5
+ <VisuallyHidden as="div">…block content…</VisuallyHidden>
6
+ ```
7
+
8
+ <!-- props:start -->
9
+
10
+ ## Props
11
+
12
+ <!-- prettier-ignore -->
13
+ | Prop | Type | Required | Description |
14
+ |---|---|---|---|
15
+ | `as` | `'span' \| 'div'` | no | Element to render. `'span'` for inline text (the common case — a link suffix, a labelling phrase). `'div'` when the hidden content is itself block-level (e.g. wraps other block elements). Default: `'span'`. |
16
+ | …native | | | plus native HTML attributes |
17
+
18
+ <!-- props:end -->
19
+
20
+ - `as?: 'span' | 'div'` — default `'span'`. Use `'div'` when the hidden content wraps other block elements.
21
+ - The "clip" technique (`position: absolute`, 1×1px, clipped) — NOT `display: none` / `visibility: hidden`, which would also remove it from assistive tech.
22
+ - `forwardRef` to the rendered element; spreads `HTMLAttributes<HTMLElement>` last (consumer wins — nothing here is semantic to protect).
23
+ - The building block `LiveRegion` renders its own announcement text into.
24
+
25
+ **When NOT to use:** to hide something from everyone, use the `hidden` attribute or a conditional render — VisuallyHidden stays reachable by assistive tech, it isn't a display toggle. On a focusable element (a skip link) — the content stays invisible even focused; there's no show-on-focus variant yet. To label a control, prefer `aria-label` or a visible `<label>` over a hidden span in the DOM flow. For announcements, use `LiveRegion` — a plain hidden span isn't live.
26
+
27
+ ```tsx
28
+ // New-tab suffix
29
+ <a href={href}>
30
+ {label}
31
+ <VisuallyHidden> (opens in a new tab)</VisuallyHidden>
32
+ </a>
33
+
34
+ // Hidden heading for a landmark
35
+ <nav aria-labelledby="site-nav-heading">
36
+ <VisuallyHidden as="div">
37
+ <Title id="site-nav-heading" order={2}>Site navigation</Title>
38
+ </VisuallyHidden>
39
+ <NavLinks />
40
+ </nav>
41
+ ```
42
+
43
+ Use it for text only screen-reader users need: a link's destination context, a landmark's hidden heading. For announcements use `<LiveRegion>{message}</LiveRegion>`, which renders a VisuallyHidden with the role / aria-live wiring.
@@ -0,0 +1,54 @@
1
+ # `<WidgetPreview>` — decorative miniature of a widget kind
2
+
3
+ A data-free, purely decorative miniature of a dashboard widget kind (KPI, list, chart, line chart, pipeline, activity). Built for the `preview` slot of `CatalogPicker` items so users can see what a widget looks like before adding it. Always `aria-hidden`; the surrounding card's title names the item.
4
+
5
+ ```tsx
6
+ import { CatalogPicker, WidgetPreview } from '@eocrm/design-system';
7
+
8
+ <CatalogPicker
9
+ label="Widget catalog"
10
+ items={[
11
+ {
12
+ id: 'open-deals',
13
+ title: 'Open deals',
14
+ preview: <WidgetPreview variant="kpi" />,
15
+ },
16
+ {
17
+ id: 'revenue',
18
+ title: 'Revenue',
19
+ preview: <WidgetPreview variant="chart" />,
20
+ },
21
+ ]}
22
+ onSelect={(id) => addWidget(id)}
23
+ />;
24
+ ```
25
+
26
+ <!-- props:start -->
27
+
28
+ ## Props
29
+
30
+ <!-- prettier-ignore -->
31
+ | Prop | Type | Required | Description |
32
+ |---|---|---|---|
33
+ | `variant` | `'kpi' \| 'list' \| 'chart' \| 'line' \| 'pipeline' \| 'activity'` | yes | Which widget kind the miniature depicts. Required. - `'kpi'` — label, a large value block (strong accent), an accented trend line. - `'list'` — rows of accented avatar + line; first avatar strong. - `'chart'` — a bar series (accented, one bar strong). - `'line'` — a line series over a light area (strong accent line). - `'pipeline'` — stage columns of cards; current stage header strong and its cards accented; next stage header accented. - `'activity'` — timeline rows with accented dots; first dot strong. |
34
+ | …native | | | plus native `<div>` attributes |
35
+
36
+ <!-- props:end -->
37
+
38
+ - **Six variants**, pick one via `variant` (required): `kpi` (label, large value, trend line), `list` (avatar + line rows), `chart` (bar series), `line` (line series over a light area), `pipeline` (stage columns of cards), `activity` (timeline rows with dots).
39
+ - **Always `aria-hidden="true"`.** The attribute is applied after your props, so it cannot be overridden. It conveys nothing to assistive tech; put the information in the item's `title` / `description`.
40
+ - **Data-free.** It takes no values. It depicts a kind of widget, never a real one.
41
+ - **Fills its container width** with a fixed 16 / 10 aspect ratio. Size it by sizing the parent (the picker card does this).
42
+ - Colours come from theme tokens, so dark mode follows automatically. Neutral pieces use `--color-border-strong` on the preview box (`--color-bg-subtle`). Accented pieces use `--color-accent` at half strength, and one hero piece per variant uses it at full strength. To retune, override `--widget-preview-bg`, `--widget-preview-shape`, `--widget-preview-accent` and `--widget-preview-accent-strong` on an ancestor. The defaults are high-contrast, so a local override added only for visibility is no longer needed.
43
+
44
+ #### When NOT to use
45
+
46
+ - ❌ A loading placeholder → `<DashboardWidget loading>` (variant-matched skeleton with the correct accessible text).
47
+ - ❌ Real data visualisation. It is a picture of a layout, not a chart.
48
+ - ❌ Anything a screen reader user must perceive. It is hidden from them by design.
49
+
50
+ #### Anti-patterns
51
+
52
+ - ❌ Expecting the preview to convey information to screen readers. Name and describe the item through `title` / `description`.
53
+ - ❌ Putting interactive content or text inside it; it is a leaf graphic.
54
+ - ❌ Using it outside a catalog or gallery context as general decoration.
@@ -0,0 +1,11 @@
1
+ # `useBelowBreakpoint` — viewport breakpoint hook
2
+
3
+ ```tsx
4
+ import { useBelowBreakpoint } from '@eocrm/design-system';
5
+
6
+ const isOverlay = useBelowBreakpoint('lg'); // true at ≤768px viewport width
7
+ ```
8
+
9
+ - Lives in `src/hooks/`, imported straight from the package root. `useBelowBreakpoint(breakpoint?: 'sm' | 'md' | 'lg'): boolean` — subscribes to `(max-width: …px)` on the **viewport** (`matchMedia`: `sm` 480 / `md` 640 / `lg` 768) and returns whether it currently matches. `breakpoint` is optional — omit it (or pass `undefined`) and the hook always returns `false`.
10
+ - Returns `false` on the server, and stays `false` until hydration corrects it — only relevant if you server-render this. In a client-only render (no SSR — the CRM's case) the value is correct from the first render.
11
+ - Viewport, not container — use it only where a container query would be circular, i.e. where the thing being measured is what the collapse changes: `<Rail>`'s own width (internal use) and `<AppLayout>`'s overlay-sidebar trigger (`sidebarOverlayBelow` — gate your `topBar` hamburger on this so it shows only while the overlay is active). For content that re-templates inside a box of stable width, use a `collapseBelow` prop (`<Grid>` / `<Split>` / `<Sortable>` / `<DashboardCanvas>` / `<DataTable>`) instead — those use container queries in CSS and need no hook.
@@ -0,0 +1,18 @@
1
+ # Calendar primitives — `useMonth`, `useWeek`, `useDay`, `useAgenda`
2
+
3
+ ```tsx
4
+ const grid = useMonth(cursorDate);
5
+ // → { year, month, monthLabel, weekdayLabels, weeks }
6
+
7
+ const week = useWeek(cursorDate);
8
+ // → { weekLabel, days, weekdayLabels }
9
+
10
+ const { day, dayLabel, dayShortLabel } = useDay(date);
11
+
12
+ const { days, rangeLabel } = useAgenda(rangeStart, rangeEnd);
13
+ ```
14
+
15
+ - Headless. These hooks return data shapes — no rendering. The Calendar UI components (Month/Week/Day/Agenda views) consume them.
16
+ - Each hook accepts an optional `options.locale` to override the Context value. `useMonth`, `useWeek`, and `useAgenda` accept `options.weekStartsOn` to override the locale-derived first day (used by `useAgenda` to compute the locale-aware column index for each `Day.weekday`).
17
+ - `Day.key` is `'YYYY-MM-DD'` in local time — safe React key, comparison handle, and event-lookup index.
18
+ - Pure date math + `Intl` formatters live alongside as utility exports: `addDays`, `startOfWeek`, `formatMonth`, `getFirstDayOfWeek`, etc. Use them if you need to derive labels or do date math outside a component.
package/docs/setup.md ADDED
@@ -0,0 +1,51 @@
1
+ # Setup (once per consuming app)
2
+
3
+ Wire the provider, styles and tokens into a consuming app once.
4
+
5
+ Two steps at your app root:
6
+
7
+ ```tsx
8
+ // 1. Import the stylesheet once (tokens, modern reset, base typography).
9
+ import '@eocrm/design-system/styles/global.scss';
10
+
11
+ // 2. Wrap your tree in <AppProvider>.
12
+ import { AppProvider } from '@eocrm/design-system';
13
+
14
+ <AppProvider locale="en" intlLocale="en-US">
15
+ <App />
16
+ </AppProvider>;
17
+ ```
18
+
19
+ `<AppProvider>` bundles the app-level contexts so you don't wire them by hand:
20
+
21
+ - `locale` (`'en' | 'ru'`) — selects the built-in UI-string bundle.
22
+ - `intlLocale?` (BCP-47, e.g. `'en-US'`) — locale for Intl formatting (Calendar, dates, numbers). Defaults to `locale`.
23
+ - `translations?` — deep-partial overrides merged over the built-in strings (rebrand a few keys; memoize the object).
24
+ - `toast?` — `<ToastViewport>` config, or `false` to mount it yourself. Omitted ⇒ mounted with defaults.
25
+ - `tokens?` — CSS design-token overrides (a flat `{ '--color-accent': '#7c3aed', '--radius-md': '6px' }` map) applied in **both** themes. Rebrands the system globally — including portaled `Modal`/`Tooltip`/`Toast`. Memoize it.
26
+ - `darkTokens?` — token overrides applied **only** in dark (forced + system), merged over `tokens` (e.g. a lighter accent on dark surfaces). Memoize it.
27
+
28
+ ```tsx
29
+ // Russian UI + a couple of rebranded strings + top-right toasts:
30
+ const translations = useMemo(() => ({ alert: { dismiss: 'Скрыть' } }), []);
31
+ <AppProvider locale="ru" translations={translations} toast={{ position: 'top-right' }}>
32
+ <App />
33
+ </AppProvider>;
34
+ ```
35
+
36
+ It composes `LocaleProvider` + `I18nProvider` and mounts the toast viewport. **Routing is yours** (`<AppProvider>` ships no router), and the stylesheet import above is still required. The individual providers (`LocaleProvider`, `I18nProvider`, `ToastViewport`) remain exported for advanced cases like pinning a subtree to a different locale.
37
+
38
+ **When NOT to use:** for a per-subtree locale / i18n override, nest `LocaleProvider` / `I18nProvider` directly — `AppProvider` is the single app root, so don't nest a second one. For a tiny embed or isolated test that only needs strings, use `I18nProvider` alone (or pass `toast={false}`) to avoid the toast viewport.
39
+
40
+ **Rebranding via tokens:**
41
+
42
+ ```tsx
43
+ const tokens = useMemo(() => ({ '--color-accent': '#7c3aed', '--radius-md': '6px' }), []);
44
+ const darkTokens = useMemo(() => ({ '--color-accent': '#a78bfa' }), []);
45
+
46
+ <AppProvider locale="en" tokens={tokens} darkTokens={darkTokens}>
47
+ <App />
48
+ </AppProvider>;
49
+ ```
50
+
51
+ `tokens` apply in light **and** dark; `darkTokens` refine the dark scope only. They're emitted as a single declarative `<style>` that layers over the [dark theme](theming.md#dark-theme) correctly, and they win over a `data-accent` preset's token blocks. One exception to "override the accent and everything follows": a preset may set the link colour apart from its accent (`tealpine` does), so when rebranding the accent on top of a preset, also override `--color-link-fg` / `--color-link-fg-hover`. Any design token can be overridden — see the generated `@eocrm/design-tokens` Sass contract for the full CSS custom-property set. Contributors change shared values only in `packages/design-tokens/src/tokens.json`; `src/styles/tokens.scss` remains the stable consumer entry point.