@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,264 @@
1
+ // RichTextAttachmentConfig.tsx — floating config popover for a ready attachment.
2
+ // Internal + presentational: the editor owns the model and passes the block's
3
+ // current values + callbacks. Mirrors RichTextLinkEditor's portal + Floating-UI
4
+ // virtual-anchor + Esc/pointerdown-outside pattern. Image attachments get alt/
5
+ // align/replace/open/download — plus width ONLY when the image renders as a
6
+ // preview (a safe, fetchable src — an embed); an uploaded object-URL image is a
7
+ // chip, so it gets no width. Non-image chips get replace/open/download.
8
+ import { useCallback, useEffect, useRef, useState } from 'react';
9
+ import { overlayStack, useFloatingSurface } from '../_internal/overlay';
10
+ import { createPortal } from 'react-dom';
11
+ import { Button } from '../Button';
12
+ import { Input } from '../Input';
13
+ import { Slider } from '../Slider';
14
+ import { Stack } from '../Stack';
15
+ import { Cluster } from '../Cluster';
16
+ import { useTranslation } from '../../i18n';
17
+ import type { Block } from '../RichText/engine/model';
18
+ import { safeHref } from '../RichText/engine/safeHref';
19
+ import { attachmentIsImage } from '../RichText/engine/attachment';
20
+ import type { Rect } from './selection';
21
+ import { useAnchoredFloating } from './useAnchoredFloating';
22
+ import { useDismissOnOutsidePointerDown } from './useDismissOnOutsidePointerDown';
23
+ import styles from './RichTextEditor.module.scss';
24
+
25
+ export interface RichTextAttachmentConfigProps {
26
+ /** The attachment block being configured (current values). */
27
+ block: Block;
28
+ /** Figure rect (viewport coords) to anchor the popover to. */
29
+ anchorRect: Rect;
30
+ /**
31
+ * Live anchor rect — re-queried by Floating UI on scroll/resize so the popover
32
+ * tracks the figure (the static `anchorRect` is only the initial position; it
33
+ * goes stale on a pure scroll). Falls back to `anchorRect` when it returns null.
34
+ */
35
+ getAnchorRect?: () => Rect | null;
36
+ /** Editor content width (px) — the upper bound for the width slider. */
37
+ maxWidth: number;
38
+ /** Native picker filter for Replace. */
39
+ accept?: string;
40
+ onAltChange: (alt: string) => void;
41
+ onAlignChange: (align: 'left' | 'center' | 'right') => void;
42
+ onWidthChange: (width: number) => void;
43
+ onWidthReset: () => void;
44
+ onReplace: (file: File) => void;
45
+ onClose: () => void;
46
+ }
47
+
48
+ const MIN_W = 80;
49
+ const ALIGNS = ['left', 'center', 'right'] as const;
50
+ const ALIGN_GLYPH: Record<(typeof ALIGNS)[number], string> = {
51
+ left: '⇤',
52
+ center: '↔',
53
+ right: '⇥',
54
+ };
55
+ const ALIGN_LABEL_KEY = {
56
+ left: 'richTextEditor.attachmentAlignLeft',
57
+ center: 'richTextEditor.attachmentAlignCenter',
58
+ right: 'richTextEditor.attachmentAlignRight',
59
+ } as const;
60
+
61
+ /**
62
+ * Internal floating config popover for a ready attachment. Rendered by
63
+ * `<RichTextEditor>` when the attachment config is open; not exported from the
64
+ * package. Image attachments get alt / align / replace / open / download — and a
65
+ * width slider ONLY when the image renders as a preview (a safe, fetchable src —
66
+ * an embedded image); an uploaded object-URL image renders as a chip and gets no
67
+ * width control. Non-image chips get replace / open / download. Remount it (via
68
+ * `key`) per open so the alt + width fields re-seed from the block.
69
+ */
70
+ export function RichTextAttachmentConfig({
71
+ block,
72
+ anchorRect,
73
+ getAnchorRect,
74
+ maxWidth,
75
+ accept,
76
+ onAltChange,
77
+ onAlignChange,
78
+ onWidthChange,
79
+ onWidthReset,
80
+ onReplace,
81
+ onClose,
82
+ }: RichTextAttachmentConfigProps) {
83
+ // #274: mounted only while open — register as a floating surface so
84
+ // Modal/Drawer/Lightbox yield Escape to us (our own Escape handling closes
85
+ // us; without registration one press would close the host too).
86
+ useFloatingSurface(true);
87
+ const t = useTranslation();
88
+ const isImage = attachmentIsImage(block);
89
+ const popRef = useRef<HTMLDivElement | null>(null);
90
+ const fileRef = useRef<HTMLInputElement | null>(null);
91
+ const seededAlt = block.alt ?? block.name ?? '';
92
+ const [alt, setAlt] = useState(seededAlt);
93
+ const sliderMax = Math.max(MIN_W + 1, Math.round(maxWidth));
94
+ const [width, setWidth] = useState<number>(
95
+ Math.max(MIN_W, Math.min(block.width ?? sliderMax, sliderMax)),
96
+ );
97
+
98
+ // Commit alt only when it differs from what was shown on open, so a focus→blur
99
+ // with no edit doesn't write the seeded `block.name` fallback into `alt`.
100
+ const commitAlt = useCallback(() => {
101
+ if (alt !== seededAlt) onAltChange(alt);
102
+ }, [alt, seededAlt, onAltChange]);
103
+
104
+ const { refs, floatingStyles } = useAnchoredFloating(anchorRect, getAnchorRect, { offset: 6 });
105
+ const setRefs = useCallback(
106
+ (node: HTMLDivElement | null) => {
107
+ popRef.current = node;
108
+ refs.setFloating(node);
109
+ },
110
+ [refs],
111
+ );
112
+
113
+ // Dismiss on a pointerdown outside the popover.
114
+ const onCloseRef = useRef(onClose);
115
+ onCloseRef.current = onClose;
116
+ useDismissOnOutsidePointerDown(popRef, onClose);
117
+
118
+ // #274: Escape from anywhere — see RichTextLinkEditor for the rationale
119
+ // (focus trap can hold focus outside this body-portaled popover).
120
+ useEffect(() => {
121
+ const onKeyDown = (e: globalThis.KeyboardEvent) => {
122
+ if (e.key !== 'Escape') return;
123
+ e.preventDefault();
124
+ overlayStack.consumeEscape(e);
125
+ onCloseRef.current();
126
+ };
127
+ document.addEventListener('keydown', onKeyDown, true);
128
+ return () => document.removeEventListener('keydown', onKeyDown, true);
129
+ }, []);
130
+
131
+ // Move focus into the popover on open so the Escape handler (on the container)
132
+ // works without the trigger keeping focus — mirrors RichTextLinkEditor focusing
133
+ // its input. Prefer the first focusable control (alt input, else first button).
134
+ useEffect(() => {
135
+ const root = popRef.current;
136
+ if (!root) return;
137
+ const focusable = root.querySelector<HTMLElement>('input, button, [tabindex]');
138
+ focusable?.focus();
139
+ }, []);
140
+
141
+ const href = safeHref(block.src ?? '');
142
+ const curAlign = block.align ?? 'left';
143
+ // Slider is single-thumb here, so its value is a number; guard a tuple defensively.
144
+ const sliderNum = (v: number | [number, number]): number => (Array.isArray(v) ? v[0] : v);
145
+
146
+ return createPortal(
147
+ <div
148
+ ref={setRefs}
149
+ className={styles.configPopover}
150
+ style={floatingStyles}
151
+ role="group"
152
+ data-rte-overlay=""
153
+ aria-label={t('richTextEditor.attachmentConfigure')}
154
+ onKeyDown={(e) => {
155
+ if (e.key === 'Escape') {
156
+ e.preventDefault();
157
+ e.stopPropagation();
158
+ onClose();
159
+ }
160
+ }}
161
+ >
162
+ <Stack gap="sm">
163
+ {isImage && (
164
+ <>
165
+ <label className={styles.configRow}>
166
+ <span className={styles.configLabel}>{t('richTextEditor.attachmentAlt')}</span>
167
+ <Input
168
+ size="sm"
169
+ value={alt}
170
+ aria-label={t('richTextEditor.attachmentAlt')}
171
+ onChange={(e) => setAlt(e.target.value)}
172
+ onBlur={commitAlt}
173
+ onKeyDown={(e) => {
174
+ if (e.key === 'Enter') {
175
+ e.preventDefault();
176
+ commitAlt();
177
+ }
178
+ }}
179
+ />
180
+ </label>
181
+ <Cluster gap="xs">
182
+ <span className={styles.configLabel}>{t('richTextEditor.attachmentAlign')}</span>
183
+ {ALIGNS.map((a) => (
184
+ <Button
185
+ key={a}
186
+ size="sm"
187
+ iconOnly
188
+ variant={curAlign === a ? 'secondary' : 'ghost'}
189
+ aria-pressed={curAlign === a}
190
+ aria-label={t(ALIGN_LABEL_KEY[a])}
191
+ onClick={() => onAlignChange(a)}
192
+ >
193
+ {ALIGN_GLYPH[a]}
194
+ </Button>
195
+ ))}
196
+ </Cluster>
197
+ {/* Width is offered only for an image that actually renders as a
198
+ preview — i.e. one with a safe, fetchable src (`href`). An uploaded
199
+ image carries an object-URL src that `safeHref` blocks, so it renders
200
+ as a download chip (RichTextAttachment uses the same isImage && href
201
+ test); resizing such a chip does nothing, so the slider is hidden.
202
+ Gating on the src (not on `block.width`) keeps it available after a
203
+ Reset and for embeds that arrived without an explicit width attr. */}
204
+ {href && (
205
+ <Cluster gap="xs">
206
+ <span className={styles.configLabel}>{t('richTextEditor.attachmentWidth')}</span>
207
+ <Slider
208
+ value={width}
209
+ min={MIN_W}
210
+ max={sliderMax}
211
+ step={1}
212
+ aria-label={t('richTextEditor.attachmentWidth')}
213
+ onChange={(v) => {
214
+ const w = sliderNum(v);
215
+ setWidth(w); // drive the thumb
216
+ onWidthChange(w); // live: resize the image on every move
217
+ }}
218
+ onChangeEnd={(v) => onWidthChange(sliderNum(v))} // seal the final value
219
+ />
220
+ <Button
221
+ size="sm"
222
+ variant="ghost"
223
+ onClick={() => {
224
+ onWidthReset();
225
+ setWidth(sliderMax); // re-seed the thumb to "natural/full"
226
+ }}
227
+ >
228
+ {t('richTextEditor.attachmentWidthReset')}
229
+ </Button>
230
+ </Cluster>
231
+ )}
232
+ </>
233
+ )}
234
+ <Cluster gap="xs">
235
+ <input
236
+ ref={fileRef}
237
+ type="file"
238
+ accept={accept}
239
+ style={{ display: 'none' }}
240
+ onChange={(e) => {
241
+ const f = e.target.files?.[0];
242
+ if (f) onReplace(f);
243
+ e.target.value = '';
244
+ }}
245
+ />
246
+ <Button size="sm" variant="ghost" onClick={() => fileRef.current?.click()}>
247
+ {t('richTextEditor.attachmentReplace')}
248
+ </Button>
249
+ {href && (
250
+ <a className={styles.configLink} href={href} target="_blank" rel="noopener noreferrer">
251
+ {t('richTextEditor.attachmentOpen')}
252
+ </a>
253
+ )}
254
+ {href && (
255
+ <a className={styles.configLink} href={href} download rel="noopener noreferrer">
256
+ {t('richTextEditor.attachmentDownload')}
257
+ </a>
258
+ )}
259
+ </Cluster>
260
+ </Stack>
261
+ </div>,
262
+ document.body,
263
+ );
264
+ }
@@ -0,0 +1,365 @@
1
+ // RichTextBlockControls.tsx — the per-block gutter overlay. Absolutely positioned
2
+ // inside the editor shell (position: relative), aligned to the active block's box.
3
+ // Lives OUTSIDE the contentEditable so it is never editable content.
4
+ import { memo, useCallback, useEffect, useMemo, useRef, type RefObject } from 'react';
5
+ import {
6
+ DndContext,
7
+ PointerSensor,
8
+ useDraggable,
9
+ useSensor,
10
+ useSensors,
11
+ type DragEndEvent,
12
+ type DragMoveEvent,
13
+ type DragStartEvent,
14
+ } from '@dnd-kit/core';
15
+ import { Button } from '../Button';
16
+ import { useTranslation } from '../../i18n';
17
+ import { RichTextBlockMenu, type BlockAction } from './RichTextBlockMenu';
18
+ import type { BlockChoice } from './RichTextToolbar';
19
+ import type { BlockType } from '../RichText/engine/model';
20
+ import { PlusIcon } from './icons';
21
+ import { preventSelectionLoss } from './preventSelectionLoss';
22
+ import { computeReflow, type BlockRect, type UnitRange } from './blockReflow';
23
+ import { gapIndexFromY } from './blockDrop';
24
+ import { useShellRelativeRect, useDraggingReporter } from './useOverlayRect';
25
+ import { tidy } from '../_internal/dragAnnouncements';
26
+ import styles from './RichTextEditor.module.scss';
27
+
28
+ export interface RichTextBlockControlsProps {
29
+ /** The editor shell element ref — used to locate block boxes + anchor overlays. */
30
+ rootRef: RefObject<HTMLElement | null>;
31
+ /** Block currently hovered or holding the caret; null hides the gutter. */
32
+ activeBlockId: string | null;
33
+ /**
34
+ * A signature of the current block order (e.g. the ids joined). The gutter's
35
+ * vertical position is measured from the active block's DOM box; the active
36
+ * block keeps its id across a reorder, so without an order-derived dependency
37
+ * the measurement would go stale and the controls would linger at the block's
38
+ * OLD row after a drop / insert / delete. Pass an order-derived string so the
39
+ * gutter re-measures whenever the block layout shifts.
40
+ */
41
+ blockOrderKey?: string;
42
+ /** Type of the active block (gates the menu's "Turn into" — hidden for voids). */
43
+ activeBlockType?: BlockType;
44
+ /** Controlled open state of the block menu. */
45
+ menuOpen: boolean;
46
+ onMenuOpenChange: (open: boolean) => void;
47
+ onInsertBelow: (blockId: string) => void;
48
+ onAction: (blockId: string, action: BlockAction) => void;
49
+ onTurnInto: (blockId: string, choice: BlockChoice) => void;
50
+ /**
51
+ * Open the block's configuration affordance (e.g. attachment settings). When
52
+ * set, a "Configure" item is added to the ⠿ block menu and fires with the
53
+ * active block id. Omit for blocks that have nothing to configure.
54
+ */
55
+ onConfigure?: (blockId: string) => void;
56
+ /**
57
+ * Set a whole-block color from the ⠿ menu's Color submenu. When set, a Color
58
+ * submenu is added to the menu and fires with the active block id, the color
59
+ * type (`textColor`/`bgColor`), and the palette key (`null` clears). Omit to
60
+ * hide the submenu.
61
+ */
62
+ onColor?: (blockId: string, type: 'textColor' | 'bgColor', key: string | null) => void;
63
+ /**
64
+ * Reorder the active block to land at `targetIndex` — a "gap" (0..N) in the
65
+ * CURRENT block array. Fired when a block drag is dropped. Wired by the editor
66
+ * to the subtree-aware `moveBlockUnitToIndex` engine transform.
67
+ */
68
+ onReorder: (blockId: string, targetIndex: number) => void;
69
+ /**
70
+ * Reports block-drag lifecycle so the editor can suppress hover-driven active-block
71
+ * changes while a drag is in progress (mirrors how `menuOpen` is mirrored into a
72
+ * ref). Called `true` on drag start, `false` on drag end/cancel.
73
+ */
74
+ onDraggingChange?: (dragging: boolean) => void;
75
+ }
76
+
77
+ // Stable draggable id — there is only ever one active gutter handle at a time.
78
+ const GUTTER_DRAGGABLE_ID = 'rte-block-gutter';
79
+
80
+ /** Strip all transient drag styles a reflow applied. */
81
+ function clearReflow(
82
+ snap: { els: HTMLElement[]; unit: UnitRange } | null,
83
+ shell: HTMLElement | null,
84
+ ): void {
85
+ if (snap) {
86
+ for (const el of snap.els) el.style.transform = '';
87
+ for (let i = snap.unit.u0; i <= snap.unit.u1; i += 1) {
88
+ snap.els[i]?.classList.remove(styles.blockLifted);
89
+ }
90
+ }
91
+ shell?.classList.remove(styles.reflowing);
92
+ }
93
+
94
+ /**
95
+ * The gutter strip, wired as the dnd-kit drag handle (the WHOLE strip — + / ⠿
96
+ * and the space around them). A sub-4px press still reaches the buttons (insert /
97
+ * open menu); a press-drag past the 4px activation lifts the row.
98
+ * Spreads only `listeners` — never dnd-kit's `attributes` — so the gutter stays out
99
+ * of the tab order (keyboard reorder is the editor's ⌘/Ctrl+⇧↑/↓ shortcuts).
100
+ */
101
+ function DraggableGutter({
102
+ top,
103
+ height,
104
+ innerRef,
105
+ children,
106
+ }: {
107
+ top: number;
108
+ height: number | null;
109
+ /** Captures the gutter DOM node so the drag can translate it with the lifted row. */
110
+ innerRef: RefObject<HTMLDivElement | null>;
111
+ children: React.ReactNode;
112
+ }) {
113
+ const { setNodeRef, listeners } = useDraggable({ id: GUTTER_DRAGGABLE_ID });
114
+ const setRefs = useCallback(
115
+ (node: HTMLDivElement | null) => {
116
+ setNodeRef(node);
117
+ innerRef.current = node;
118
+ },
119
+ [setNodeRef, innerRef],
120
+ );
121
+ return (
122
+ <div
123
+ ref={setRefs}
124
+ className={styles.gutter}
125
+ style={{ top, height: height ?? undefined }}
126
+ contentEditable={false}
127
+ {...listeners}
128
+ >
129
+ {children}
130
+ </div>
131
+ );
132
+ }
133
+
134
+ /**
135
+ * Internal: the gutter overlay for the active block. Measures the block element's
136
+ * vertical offset within the shell and renders the `+` insert button + the block
137
+ * menu there. Renders nothing when there is no active block. The whole gutter is
138
+ * the drag handle: dragging it reorders the active block via an in-place reflow,
139
+ * while a plain click on +/⠿ still triggers that button. Block configuration
140
+ * (e.g. attachment settings) lives in the ⠿ menu's "Configure" item, not a
141
+ * separate gutter button.
142
+ */
143
+ export const RichTextBlockControls = memo(function RichTextBlockControls({
144
+ rootRef,
145
+ activeBlockId,
146
+ blockOrderKey,
147
+ activeBlockType,
148
+ menuOpen,
149
+ onMenuOpenChange,
150
+ onInsertBelow,
151
+ onAction,
152
+ onTurnInto,
153
+ onConfigure,
154
+ onColor,
155
+ onReorder,
156
+ onDraggingChange,
157
+ }: RichTextBlockControlsProps) {
158
+ const t = useTranslation();
159
+ // Drag snapshot, captured once at drag start (measuring transformed DOM would feed
160
+ // back on itself). null when not dragging.
161
+ const dragRef = useRef<{
162
+ rects: BlockRect[];
163
+ els: HTMLElement[];
164
+ unit: UnitRange;
165
+ parentIdx: number[];
166
+ } | null>(null);
167
+ // Block id captured at drag start — reorder by this, not the live activeBlockId.
168
+ const draggedIdRef = useRef<string | null>(null);
169
+ // The gutter DOM node, so the drag can translate it in lockstep with the lifted row.
170
+ const gutterElRef = useRef<HTMLDivElement | null>(null);
171
+ // The dragged block's own text, captured at drag start so the announcement can
172
+ // name it after the reflow has been cleared.
173
+ const dragLabelRef = useRef('');
174
+
175
+ // Reports block-drag lifecycle + fires (false) on a mid-drag unmount so nothing
176
+ // leaks (dnd-kit fires neither end nor cancel when the controls unmount).
177
+ const reportDragging = useDraggingReporter(onDraggingChange);
178
+
179
+ // If the controls unmount mid-drag (blockControls turned off, or the editor
180
+ // unmounts), clear any applied reflow transforms. The dragging-state report is
181
+ // handled by useDraggingReporter; this effect owns the DOM-style cleanup. Order:
182
+ // this effect is registered AFTER the reporter, so its cleanup runs FIRST —
183
+ // clearReflow then onDraggingChange(false), matching the original order.
184
+ useEffect(() => {
185
+ return () => {
186
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- clears the reflow on the root as it is at unmount
187
+ clearReflow(dragRef.current, rootRef.current);
188
+ dragRef.current = null;
189
+ };
190
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- unmount-only cleanup
191
+ }, []);
192
+
193
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }));
194
+
195
+ // Measure the active block's box relative to the shell. getEl folds in
196
+ // activeBlockId (null → no target); blockOrderKey + menuOpen drive re-measure via
197
+ // `key` — a reorder/insert/delete keeps the active block's id but moves its row, so
198
+ // an order-derived key re-measures rather than leaving the gutter stranded.
199
+ const blockEl = useCallback(
200
+ () =>
201
+ activeBlockId
202
+ ? (rootRef.current?.querySelector<HTMLElement>(
203
+ `[data-block-id="${CSS.escape(activeBlockId)}"]`,
204
+ ) ?? null)
205
+ : null,
206
+ [rootRef, activeBlockId],
207
+ );
208
+ const rect = useShellRelativeRect(rootRef, blockEl, `${blockOrderKey ?? ''}|${menuOpen}`);
209
+ const top = rect?.top ?? null;
210
+ const height = rect?.height ?? null;
211
+
212
+ const handleDragStart = (_event: DragStartEvent) => {
213
+ const root = rootRef.current;
214
+ if (!activeBlockId || !root) return;
215
+
216
+ const shellTop = root.getBoundingClientRect().top;
217
+ const nodes = Array.from(root.querySelectorAll<HTMLElement>('[data-block-id]'));
218
+ const rects: BlockRect[] = nodes.map((el) => {
219
+ const b = el.getBoundingClientRect();
220
+ return { top: b.top - shellTop, height: b.height };
221
+ });
222
+ // The dragged unit = the active block element PLUS its nested descendant blocks
223
+ // (renderDoc nests deeper list items inside the parent <li>) — a contiguous run.
224
+ const activeEl = nodes.find((el) => el.getAttribute('data-block-id') === activeBlockId);
225
+ const unitIds = new Set<string>([activeBlockId]);
226
+ activeEl?.querySelectorAll<HTMLElement>('[data-block-id]').forEach((d) => {
227
+ const id = d.getAttribute('data-block-id');
228
+ if (id) unitIds.add(id);
229
+ });
230
+ const idxs: number[] = [];
231
+ nodes.forEach((el, i) => {
232
+ const id = el.getAttribute('data-block-id');
233
+ if (id && unitIds.has(id)) idxs.push(i);
234
+ });
235
+ if (idxs.length === 0) return;
236
+ const unit: UnitRange = { u0: idxs[0], u1: idxs[idxs.length - 1] };
237
+
238
+ // For each box, the index of its nearest [data-block-id] ANCESTOR (or -1). CSS
239
+ // transforms inherit, so a nested box's own translate is offset against its
240
+ // ancestor's in handleDragMove to land at exactly the desired shift.
241
+ const indexOf = new Map<HTMLElement, number>(nodes.map((el, i) => [el, i]));
242
+ const parentIdx = nodes.map((el) => {
243
+ const anc = el.parentElement?.closest<HTMLElement>('[data-block-id]') ?? null;
244
+ return anc && indexOf.has(anc) ? (indexOf.get(anc) as number) : -1;
245
+ });
246
+
247
+ draggedIdRef.current = activeBlockId;
248
+ dragLabelRef.current = tidy(nodes[unit.u0].textContent ?? '');
249
+ onMenuOpenChange(false); // a drag should never leave the block menu open
250
+ reportDragging(true);
251
+ dragRef.current = { rects, els: nodes, unit, parentIdx };
252
+ root.classList.add(styles.reflowing);
253
+ nodes[unit.u0].classList.add(styles.blockLifted);
254
+ };
255
+
256
+ const handleDragMove = (event: DragMoveEvent) => {
257
+ const snap = dragRef.current;
258
+ const root = rootRef.current;
259
+ if (!snap || !root) return;
260
+ const activator = event.activatorEvent as PointerEvent;
261
+ const initialY = typeof activator?.clientY === 'number' ? activator.clientY : null;
262
+ if (initialY == null) return;
263
+ const pointerY = initialY + event.delta.y - root.getBoundingClientRect().top;
264
+ const reflow = computeReflow(snap.rects, snap.unit, event.delta.y, pointerY);
265
+ // Transforms inherit: set each box's OWN transform to the desired shift minus its
266
+ // ancestor's desired shift, so inheritance composes to exactly shifts[i].
267
+ for (let i = 0; i < snap.els.length; i += 1) {
268
+ const pid = snap.parentIdx[i];
269
+ const own = reflow.shifts[i] - (pid >= 0 ? reflow.shifts[pid] : 0);
270
+ snap.els[i].style.transform = own ? `translateY(${own}px)` : '';
271
+ }
272
+ // Carry the gutter (+ / ⠿) along with the lifted row by the same clamped
273
+ // travel, so the controls feel attached to the row being dragged. The gutter is
274
+ // not nested, so it shifts by the unit's net movement (liftDy) directly.
275
+ if (gutterElRef.current) {
276
+ gutterElRef.current.style.transform = reflow.liftDy ? `translateY(${reflow.liftDy}px)` : '';
277
+ }
278
+ };
279
+
280
+ const endDrag = () => {
281
+ clearReflow(dragRef.current, rootRef.current);
282
+ if (gutterElRef.current) gutterElRef.current.style.transform = '';
283
+ dragRef.current = null;
284
+ draggedIdRef.current = null;
285
+ reportDragging(false);
286
+ };
287
+
288
+ const handleDragEnd = (event: DragEndEvent) => {
289
+ const snap = dragRef.current;
290
+ const root = rootRef.current;
291
+ const id = draggedIdRef.current;
292
+ let gap: number | null = null;
293
+ if (snap && root) {
294
+ const activator = event.activatorEvent as PointerEvent;
295
+ const initialY = typeof activator?.clientY === 'number' ? activator.clientY : null;
296
+ if (initialY != null) {
297
+ const pointerY = initialY + event.delta.y - root.getBoundingClientRect().top;
298
+ gap = gapIndexFromY(snap.rects, pointerY);
299
+ }
300
+ }
301
+ endDrag(); // clear transforms BEFORE the reorder re-render so no inline styles linger
302
+ if (id != null && gap != null) onReorder(id, gap);
303
+ };
304
+
305
+ const handleDragCancel = () => {
306
+ endDrag();
307
+ };
308
+
309
+ // Localized announcements (Hard rule 9, #390). This context deliberately does
310
+ // NOT go through `useDragAccessibility`: it registers no droppables (the drop
311
+ // slot is computed from the pointer against the document flow), so `over` is
312
+ // always null and the shared over-driven messages would all be wrong here.
313
+ // Same `drag.*` copy, three of the five callbacks.
314
+ const accessibility = useMemo(() => {
315
+ const item = () => dragLabelRef.current || t('drag.unnamed');
316
+ return {
317
+ announcements: {
318
+ onDragStart: () => t('drag.pickedUp', { item: item() }),
319
+ // Silent: with no droppables, dnd-kit's per-move announcement would be
320
+ // a permanent, false "not over a drop target".
321
+ onDragOver: () => undefined,
322
+ onDragEnd: () => t('drag.moved', { item: item() }),
323
+ onDragCancel: () => t('drag.cancelled', { item: item() }),
324
+ },
325
+ screenReaderInstructions: { draggable: t('drag.instructions') },
326
+ };
327
+ }, [t]);
328
+
329
+ if (!activeBlockId || top == null) return null;
330
+
331
+ return (
332
+ <DndContext
333
+ accessibility={accessibility}
334
+ sensors={sensors}
335
+ onDragStart={handleDragStart}
336
+ onDragMove={handleDragMove}
337
+ onDragEnd={handleDragEnd}
338
+ onDragCancel={handleDragCancel}
339
+ >
340
+ <DraggableGutter top={top} height={height} innerRef={gutterElRef}>
341
+ <Button
342
+ size="sm"
343
+ variant="ghost"
344
+ iconOnly
345
+ tabIndex={-1}
346
+ aria-label={t('richTextEditor.blockInsert')}
347
+ className={styles.gutterButton}
348
+ onMouseDown={preventSelectionLoss}
349
+ onClick={() => onInsertBelow(activeBlockId)}
350
+ >
351
+ <PlusIcon />
352
+ </Button>
353
+ <RichTextBlockMenu
354
+ open={menuOpen}
355
+ onOpenChange={onMenuOpenChange}
356
+ onAction={(a) => onAction(activeBlockId, a)}
357
+ onTurnInto={(c) => onTurnInto(activeBlockId, c)}
358
+ blockType={activeBlockType}
359
+ onConfigure={onConfigure ? () => onConfigure(activeBlockId) : undefined}
360
+ onColor={onColor ? (type, key) => onColor(activeBlockId, type, key) : undefined}
361
+ />
362
+ </DraggableGutter>
363
+ </DndContext>
364
+ );
365
+ });