@eocrm/design-system 0.0.0-stage → 0.6.18

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 (898) hide show
  1. package/AI-PRIMER.md +341 -0
  2. package/LICENSE +202 -0
  3. package/README.md +266 -2
  4. package/docs/components/Accordion.md +114 -0
  5. package/docs/components/AgentAvatar.md +58 -0
  6. package/docs/components/Alert.md +81 -0
  7. package/docs/components/AppLayout.md +70 -0
  8. package/docs/components/Avatar.md +49 -0
  9. package/docs/components/AvatarGroup.md +47 -0
  10. package/docs/components/Badge.md +60 -0
  11. package/docs/components/Banner.md +89 -0
  12. package/docs/components/BrandIcon.md +32 -0
  13. package/docs/components/Breadcrumb.md +72 -0
  14. package/docs/components/Button.md +107 -0
  15. package/docs/components/ButtonGroup.md +78 -0
  16. package/docs/components/Calendar.md +158 -0
  17. package/docs/components/Card.md +165 -0
  18. package/docs/components/CatalogPicker.md +83 -0
  19. package/docs/components/Chart.md +114 -0
  20. package/docs/components/ChatBubble.md +55 -0
  21. package/docs/components/ChatLauncher.md +97 -0
  22. package/docs/components/Checkbox.md +55 -0
  23. package/docs/components/CircularProgress.md +53 -0
  24. package/docs/components/Cluster.md +96 -0
  25. package/docs/components/Code.md +35 -0
  26. package/docs/components/CodeBlock.md +67 -0
  27. package/docs/components/ColorPicker.md +115 -0
  28. package/docs/components/ConfirmationPopover.md +70 -0
  29. package/docs/components/Constrain.md +39 -0
  30. package/docs/components/CurrencySelect.md +57 -0
  31. package/docs/components/CursorPagination.md +43 -0
  32. package/docs/components/DashboardCanvas.md +79 -0
  33. package/docs/components/DashboardWidget.md +131 -0
  34. package/docs/components/DataTable.md +88 -0
  35. package/docs/components/DatePicker.md +68 -0
  36. package/docs/components/DateRangePicker.md +71 -0
  37. package/docs/components/DateStrip.md +56 -0
  38. package/docs/components/DefinitionList.md +82 -0
  39. package/docs/components/Divider.md +57 -0
  40. package/docs/components/Dot.md +26 -0
  41. package/docs/components/Drawer.md +94 -0
  42. package/docs/components/DropdownMenu.md +299 -0
  43. package/docs/components/EmojiPicker.md +84 -0
  44. package/docs/components/EmptyState.md +55 -0
  45. package/docs/components/EntityChip.md +102 -0
  46. package/docs/components/ErrorState.md +72 -0
  47. package/docs/components/Field.md +91 -0
  48. package/docs/components/FileUpload.md +109 -0
  49. package/docs/components/FilterChip.md +88 -0
  50. package/docs/components/FlowCanvas.md +108 -0
  51. package/docs/components/FormRow.md +31 -0
  52. package/docs/components/FormSection.md +37 -0
  53. package/docs/components/Grid.md +103 -0
  54. package/docs/components/Highlight.md +75 -0
  55. package/docs/components/HighlightedText.md +50 -0
  56. package/docs/components/IconPicker.md +134 -0
  57. package/docs/components/IconTile.md +30 -0
  58. package/docs/components/Image.md +84 -0
  59. package/docs/components/ImageCrop.md +163 -0
  60. package/docs/components/Indent.md +31 -0
  61. package/docs/components/InlineDatePicker.md +58 -0
  62. package/docs/components/InlineDateRangePicker.md +57 -0
  63. package/docs/components/Input.md +54 -0
  64. package/docs/components/Kanban.md +122 -0
  65. package/docs/components/Kbd.md +41 -0
  66. package/docs/components/Lightbox.md +105 -0
  67. package/docs/components/Link.md +65 -0
  68. package/docs/components/LinkCard.md +41 -0
  69. package/docs/components/LiquidEditor.md +84 -0
  70. package/docs/components/List.md +68 -0
  71. package/docs/components/LiveRegion.md +29 -0
  72. package/docs/components/LocaleProvider.md +25 -0
  73. package/docs/components/Logo.md +41 -0
  74. package/docs/components/Masonry.md +48 -0
  75. package/docs/components/MediaTile.md +95 -0
  76. package/docs/components/Modal.md +107 -0
  77. package/docs/components/MoneyInput.md +62 -0
  78. package/docs/components/OptionsPicker.md +123 -0
  79. package/docs/components/OtpInput.md +65 -0
  80. package/docs/components/Page.md +35 -0
  81. package/docs/components/PageHeader.md +133 -0
  82. package/docs/components/Pagination.md +44 -0
  83. package/docs/components/Palette.md +32 -0
  84. package/docs/components/PasswordInput.md +45 -0
  85. package/docs/components/PasswordStrengthMeter.md +27 -0
  86. package/docs/components/PersonDisplay.md +153 -0
  87. package/docs/components/PhoneInput.md +54 -0
  88. package/docs/components/PillMenu.md +91 -0
  89. package/docs/components/Popover.md +127 -0
  90. package/docs/components/Progress.md +56 -0
  91. package/docs/components/QrCode.md +34 -0
  92. package/docs/components/Radio.md +37 -0
  93. package/docs/components/RadioGroup.md +56 -0
  94. package/docs/components/Rail.md +191 -0
  95. package/docs/components/RelativeDateInput.md +114 -0
  96. package/docs/components/RichText.md +44 -0
  97. package/docs/components/RichTextEditor.md +112 -0
  98. package/docs/components/Screen.md +37 -0
  99. package/docs/components/ScrollArea.md +39 -0
  100. package/docs/components/Select.md +131 -0
  101. package/docs/components/SettingRow.md +98 -0
  102. package/docs/components/Skeleton.md +68 -0
  103. package/docs/components/Slider.md +92 -0
  104. package/docs/components/SlotGrid.md +55 -0
  105. package/docs/components/SocialButton.md +31 -0
  106. package/docs/components/Sortable.md +127 -0
  107. package/docs/components/SortableGroup.md +52 -0
  108. package/docs/components/Sparkline.md +51 -0
  109. package/docs/components/Split.md +76 -0
  110. package/docs/components/Stack.md +59 -0
  111. package/docs/components/StagePath.md +66 -0
  112. package/docs/components/StatGroup.md +61 -0
  113. package/docs/components/StatTile.md +58 -0
  114. package/docs/components/Sticky.md +69 -0
  115. package/docs/components/Switch.md +89 -0
  116. package/docs/components/Table.md +184 -0
  117. package/docs/components/TableOfContents.md +76 -0
  118. package/docs/components/Tabs.md +94 -0
  119. package/docs/components/Text.md +63 -0
  120. package/docs/components/Textarea.md +59 -0
  121. package/docs/components/Thread.md +52 -0
  122. package/docs/components/TimeField.md +70 -0
  123. package/docs/components/Timeline.md +57 -0
  124. package/docs/components/Title.md +54 -0
  125. package/docs/components/ToastViewport.md +61 -0
  126. package/docs/components/Tooltip.md +63 -0
  127. package/docs/components/TopBar.md +214 -0
  128. package/docs/components/Tour.md +85 -0
  129. package/docs/components/TreeView.md +113 -0
  130. package/docs/components/VisuallyHidden.md +43 -0
  131. package/docs/components/WidgetPreview.md +54 -0
  132. package/docs/components/useBelowBreakpoint.md +11 -0
  133. package/docs/components/useMonth.md +18 -0
  134. package/docs/setup.md +51 -0
  135. package/docs/theming.md +95 -0
  136. package/docs/tokens.md +123 -0
  137. package/docs/transient-state.md +56 -0
  138. package/package.json +86 -4
  139. package/src/_meta/manifest.ts +293 -0
  140. package/src/app/AppProvider.tsx +78 -0
  141. package/src/app/index.ts +3 -0
  142. package/src/app/themeTokens.ts +95 -0
  143. package/src/calendar/dateMath.ts +114 -0
  144. package/src/calendar/formatters.ts +75 -0
  145. package/src/calendar/index.ts +39 -0
  146. package/src/calendar/types.ts +36 -0
  147. package/src/calendar/useAgenda.ts +70 -0
  148. package/src/calendar/useDay.ts +51 -0
  149. package/src/calendar/useMonth.ts +82 -0
  150. package/src/calendar/useWeek.ts +62 -0
  151. package/src/calendar/weekInfo.ts +83 -0
  152. package/src/components/Accordion/Accordion.module.scss +304 -0
  153. package/src/components/Accordion/Accordion.tokens.scss +64 -0
  154. package/src/components/Accordion/Accordion.tsx +272 -0
  155. package/src/components/Accordion/AccordionContent.tsx +36 -0
  156. package/src/components/Accordion/AccordionItem.tsx +66 -0
  157. package/src/components/Accordion/AccordionTrigger.tsx +121 -0
  158. package/src/components/Accordion/context.ts +47 -0
  159. package/src/components/Accordion/index.ts +14 -0
  160. package/src/components/Alert/Alert.module.scss +92 -0
  161. package/src/components/Alert/Alert.tokens.scss +60 -0
  162. package/src/components/Alert/Alert.tsx +136 -0
  163. package/src/components/Alert/index.ts +2 -0
  164. package/src/components/AppLayout/AppLayout.module.scss +130 -0
  165. package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
  166. package/src/components/AppLayout/AppLayout.tsx +211 -0
  167. package/src/components/AppLayout/index.ts +2 -0
  168. package/src/components/Avatar/AgentAvatar.module.scss +117 -0
  169. package/src/components/Avatar/AgentAvatar.tsx +122 -0
  170. package/src/components/Avatar/Avatar.module.scss +181 -0
  171. package/src/components/Avatar/Avatar.tokens.scss +107 -0
  172. package/src/components/Avatar/Avatar.tsx +210 -0
  173. package/src/components/Avatar/AvatarGroup.module.scss +128 -0
  174. package/src/components/Avatar/AvatarGroup.tsx +119 -0
  175. package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
  176. package/src/components/Avatar/index.ts +6 -0
  177. package/src/components/Badge/Badge.module.scss +124 -0
  178. package/src/components/Badge/Badge.tokens.scss +74 -0
  179. package/src/components/Badge/Badge.tsx +164 -0
  180. package/src/components/Badge/index.ts +2 -0
  181. package/src/components/Banner/Banner.module.scss +73 -0
  182. package/src/components/Banner/Banner.tokens.scss +51 -0
  183. package/src/components/Banner/Banner.tsx +138 -0
  184. package/src/components/Banner/index.ts +2 -0
  185. package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
  186. package/src/components/BrandIcon/BrandIcon.tsx +99 -0
  187. package/src/components/BrandIcon/index.ts +2 -0
  188. package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
  189. package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
  190. package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
  191. package/src/components/Breadcrumb/index.ts +2 -0
  192. package/src/components/Button/Button.module.scss +167 -0
  193. package/src/components/Button/Button.tokens.scss +90 -0
  194. package/src/components/Button/Button.tsx +205 -0
  195. package/src/components/Button/index.ts +2 -0
  196. package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
  197. package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
  198. package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
  199. package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
  200. package/src/components/ButtonGroup/context.ts +45 -0
  201. package/src/components/ButtonGroup/index.ts +2 -0
  202. package/src/components/Calendar/AgendaView.module.scss +231 -0
  203. package/src/components/Calendar/AgendaView.tsx +214 -0
  204. package/src/components/Calendar/AllDayBand.module.scss +18 -0
  205. package/src/components/Calendar/AllDayBand.tsx +75 -0
  206. package/src/components/Calendar/Calendar.module.scss +23 -0
  207. package/src/components/Calendar/Calendar.tokens.scss +262 -0
  208. package/src/components/Calendar/Calendar.tsx +370 -0
  209. package/src/components/Calendar/DayCell.module.scss +30 -0
  210. package/src/components/Calendar/DayCell.tsx +50 -0
  211. package/src/components/Calendar/DayView.module.scss +10 -0
  212. package/src/components/Calendar/DayView.tsx +163 -0
  213. package/src/components/Calendar/EventChip.module.scss +171 -0
  214. package/src/components/Calendar/EventChip.tsx +115 -0
  215. package/src/components/Calendar/HourGrid.module.scss +123 -0
  216. package/src/components/Calendar/HourGrid.tsx +381 -0
  217. package/src/components/Calendar/MonthView.module.scss +99 -0
  218. package/src/components/Calendar/MonthView.tsx +296 -0
  219. package/src/components/Calendar/TimedEvent.module.scss +205 -0
  220. package/src/components/Calendar/TimedEvent.tsx +247 -0
  221. package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
  222. package/src/components/Calendar/ViewSwitcher.tsx +47 -0
  223. package/src/components/Calendar/WeekView.module.scss +10 -0
  224. package/src/components/Calendar/WeekView.tsx +137 -0
  225. package/src/components/Calendar/eventColor.ts +60 -0
  226. package/src/components/Calendar/index.ts +18 -0
  227. package/src/components/Calendar/types.ts +451 -0
  228. package/src/components/Calendar/useEventDrag.ts +783 -0
  229. package/src/components/Calendar/utils.ts +622 -0
  230. package/src/components/Card/Card.module.scss +264 -0
  231. package/src/components/Card/Card.tokens.scss +55 -0
  232. package/src/components/Card/Card.tsx +170 -0
  233. package/src/components/Card/CardBody.tsx +45 -0
  234. package/src/components/Card/CardHeader.tsx +113 -0
  235. package/src/components/Card/CardList.tsx +24 -0
  236. package/src/components/Card/CardListRow.tsx +24 -0
  237. package/src/components/Card/index.ts +7 -0
  238. package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
  239. package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
  240. package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
  241. package/src/components/CatalogPicker/index.ts +2 -0
  242. package/src/components/Chart/Chart.module.scss +287 -0
  243. package/src/components/Chart/Chart.tokens.scss +63 -0
  244. package/src/components/Chart/Chart.tsx +607 -0
  245. package/src/components/Chart/ChartLegend.tsx +99 -0
  246. package/src/components/Chart/ChartTable.tsx +62 -0
  247. package/src/components/Chart/ChartTooltip.tsx +91 -0
  248. package/src/components/Chart/chartModel.ts +689 -0
  249. package/src/components/Chart/index.ts +2 -0
  250. package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
  251. package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
  252. package/src/components/ChatBubble/ChatBubble.tsx +61 -0
  253. package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
  254. package/src/components/ChatBubble/index.ts +3 -0
  255. package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
  256. package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
  257. package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
  258. package/src/components/ChatLauncher/index.ts +2 -0
  259. package/src/components/ChatLauncher/isAtBottom.ts +12 -0
  260. package/src/components/Checkbox/Checkbox.module.scss +147 -0
  261. package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
  262. package/src/components/Checkbox/Checkbox.tsx +188 -0
  263. package/src/components/Checkbox/index.ts +2 -0
  264. package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
  265. package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
  266. package/src/components/CircularProgress/CircularProgress.tsx +139 -0
  267. package/src/components/CircularProgress/index.ts +7 -0
  268. package/src/components/Cluster/Cluster.module.scss +145 -0
  269. package/src/components/Cluster/Cluster.tokens.scss +11 -0
  270. package/src/components/Cluster/Cluster.tsx +215 -0
  271. package/src/components/Cluster/index.ts +2 -0
  272. package/src/components/Code/Code.module.scss +28 -0
  273. package/src/components/Code/Code.tokens.scss +15 -0
  274. package/src/components/Code/Code.tsx +44 -0
  275. package/src/components/Code/index.ts +2 -0
  276. package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
  277. package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
  278. package/src/components/CodeBlock/CodeBlock.tsx +274 -0
  279. package/src/components/CodeBlock/highlight.ts +179 -0
  280. package/src/components/CodeBlock/index.ts +8 -0
  281. package/src/components/CodeBlock/sampleSync.ts +42 -0
  282. package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
  283. package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
  284. package/src/components/ColorPicker/ColorPicker.tsx +367 -0
  285. package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
  286. package/src/components/ColorPicker/SVSquare.tsx +189 -0
  287. package/src/components/ColorPicker/colorMath.ts +141 -0
  288. package/src/components/ColorPicker/index.ts +6 -0
  289. package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
  290. package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
  291. package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
  292. package/src/components/ConfirmationPopover/index.ts +2 -0
  293. package/src/components/Constrain/Constrain.module.scss +99 -0
  294. package/src/components/Constrain/Constrain.tsx +79 -0
  295. package/src/components/Constrain/index.ts +2 -0
  296. package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
  297. package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
  298. package/src/components/CurrencySelect/index.ts +3 -0
  299. package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
  300. package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
  301. package/src/components/CursorPagination/CursorPagination.tsx +121 -0
  302. package/src/components/CursorPagination/index.ts +2 -0
  303. package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
  304. package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
  305. package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
  306. package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
  307. package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
  308. package/src/components/DashboardCanvas/engine.ts +363 -0
  309. package/src/components/DashboardCanvas/index.ts +9 -0
  310. package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
  311. package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
  312. package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
  313. package/src/components/DashboardWidget/index.ts +7 -0
  314. package/src/components/DataTable/BodyRow.tsx +197 -0
  315. package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
  316. package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
  317. package/src/components/DataTable/DataTable.module.scss +511 -0
  318. package/src/components/DataTable/DataTable.tokens.scss +80 -0
  319. package/src/components/DataTable/DataTable.tsx +734 -0
  320. package/src/components/DataTable/HeaderCell.module.scss +215 -0
  321. package/src/components/DataTable/HeaderCell.tsx +440 -0
  322. package/src/components/DataTable/columnShift.ts +117 -0
  323. package/src/components/DataTable/index.ts +23 -0
  324. package/src/components/DataTable/pinStyle.ts +47 -0
  325. package/src/components/DataTable/reorderColumns.ts +66 -0
  326. package/src/components/DataTable/types.ts +289 -0
  327. package/src/components/DataTable/useColumnDragShift.ts +216 -0
  328. package/src/components/DataTable/useDataTable.ts +372 -0
  329. package/src/components/DataTable/useResizeHandle.ts +97 -0
  330. package/src/components/DatePicker/DatePicker.module.scss +180 -0
  331. package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
  332. package/src/components/DatePicker/DatePicker.tsx +664 -0
  333. package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
  334. package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
  335. package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
  336. package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
  337. package/src/components/DatePicker/index.ts +4 -0
  338. package/src/components/DatePicker/utils.ts +364 -0
  339. package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
  340. package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
  341. package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
  342. package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
  343. package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
  344. package/src/components/DateRangePicker/index.ts +5 -0
  345. package/src/components/DateRangePicker/utils.ts +151 -0
  346. package/src/components/DateStrip/DateStrip.module.scss +78 -0
  347. package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
  348. package/src/components/DateStrip/DateStrip.tsx +205 -0
  349. package/src/components/DateStrip/index.ts +2 -0
  350. package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
  351. package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
  352. package/src/components/DefinitionList/DefinitionList.tsx +198 -0
  353. package/src/components/DefinitionList/index.ts +9 -0
  354. package/src/components/Divider/Divider.module.scss +144 -0
  355. package/src/components/Divider/Divider.tokens.scss +21 -0
  356. package/src/components/Divider/Divider.tsx +103 -0
  357. package/src/components/Divider/index.ts +2 -0
  358. package/src/components/Dot/Dot.module.scss +40 -0
  359. package/src/components/Dot/Dot.tokens.scss +4 -0
  360. package/src/components/Dot/Dot.tsx +45 -0
  361. package/src/components/Dot/index.ts +2 -0
  362. package/src/components/Drawer/Body.tsx +23 -0
  363. package/src/components/Drawer/Close.tsx +35 -0
  364. package/src/components/Drawer/Content.tsx +93 -0
  365. package/src/components/Drawer/Drawer.module.scss +232 -0
  366. package/src/components/Drawer/Drawer.tokens.scss +38 -0
  367. package/src/components/Drawer/Drawer.tsx +23 -0
  368. package/src/components/Drawer/DrawerRoot.tsx +190 -0
  369. package/src/components/Drawer/Footer.tsx +24 -0
  370. package/src/components/Drawer/Header.tsx +64 -0
  371. package/src/components/Drawer/Overlay.tsx +82 -0
  372. package/src/components/Drawer/context.ts +44 -0
  373. package/src/components/Drawer/index.ts +12 -0
  374. package/src/components/Drawer/useDragToClose.ts +149 -0
  375. package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
  376. package/src/components/DropdownMenu/Content.tsx +419 -0
  377. package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
  378. package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
  379. package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
  380. package/src/components/DropdownMenu/Group.tsx +76 -0
  381. package/src/components/DropdownMenu/Item.tsx +148 -0
  382. package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
  383. package/src/components/DropdownMenu/Radio.tsx +178 -0
  384. package/src/components/DropdownMenu/Root.tsx +100 -0
  385. package/src/components/DropdownMenu/Sub.tsx +332 -0
  386. package/src/components/DropdownMenu/Trigger.tsx +76 -0
  387. package/src/components/DropdownMenu/context.ts +65 -0
  388. package/src/components/DropdownMenu/index.ts +20 -0
  389. package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
  390. package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
  391. package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
  392. package/src/components/EmojiPicker/emojiData.ts +245 -0
  393. package/src/components/EmojiPicker/index.ts +3 -0
  394. package/src/components/EmptyState/EmptyState.module.scss +102 -0
  395. package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
  396. package/src/components/EmptyState/EmptyState.tsx +112 -0
  397. package/src/components/EmptyState/index.ts +7 -0
  398. package/src/components/EntityChip/EntityChip.module.scss +275 -0
  399. package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
  400. package/src/components/EntityChip/EntityChip.tsx +649 -0
  401. package/src/components/EntityChip/index.ts +10 -0
  402. package/src/components/ErrorState/ErrorState.module.scss +105 -0
  403. package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
  404. package/src/components/ErrorState/ErrorState.tsx +125 -0
  405. package/src/components/ErrorState/index.ts +8 -0
  406. package/src/components/Field/Field.module.scss +46 -0
  407. package/src/components/Field/Field.tsx +185 -0
  408. package/src/components/Field/index.ts +2 -0
  409. package/src/components/FileUpload/FileUpload.module.scss +187 -0
  410. package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
  411. package/src/components/FileUpload/FileUpload.tsx +569 -0
  412. package/src/components/FileUpload/formatBytes.ts +34 -0
  413. package/src/components/FileUpload/iconForFile.ts +40 -0
  414. package/src/components/FileUpload/index.ts +2 -0
  415. package/src/components/FilterChip/FilterChip.module.scss +61 -0
  416. package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
  417. package/src/components/FilterChip/FilterChip.tsx +208 -0
  418. package/src/components/FilterChip/index.ts +5 -0
  419. package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
  420. package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
  421. package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
  422. package/src/components/FlowCanvas/FlowControls.tsx +46 -0
  423. package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
  424. package/src/components/FlowCanvas/FlowNode.tsx +76 -0
  425. package/src/components/FlowCanvas/edgePath.ts +85 -0
  426. package/src/components/FlowCanvas/index.ts +4 -0
  427. package/src/components/FlowCanvas/layout.ts +148 -0
  428. package/src/components/FlowCanvas/spatialNav.ts +76 -0
  429. package/src/components/FlowCanvas/types.ts +59 -0
  430. package/src/components/FlowCanvas/useViewport.ts +122 -0
  431. package/src/components/FormRow/FormRow.module.scss +2 -0
  432. package/src/components/FormRow/FormRow.tsx +37 -0
  433. package/src/components/FormRow/index.ts +2 -0
  434. package/src/components/FormSection/FormSection.module.scss +24 -0
  435. package/src/components/FormSection/FormSection.tsx +46 -0
  436. package/src/components/FormSection/index.ts +2 -0
  437. package/src/components/Grid/Grid.module.scss +162 -0
  438. package/src/components/Grid/Grid.tokens.scss +13 -0
  439. package/src/components/Grid/Grid.tsx +226 -0
  440. package/src/components/Grid/GridItem.tsx +77 -0
  441. package/src/components/Grid/index.ts +11 -0
  442. package/src/components/Highlight/Highlight.module.scss +43 -0
  443. package/src/components/Highlight/Highlight.tokens.scss +35 -0
  444. package/src/components/Highlight/Highlight.tsx +164 -0
  445. package/src/components/Highlight/HighlightOverlay.tsx +100 -0
  446. package/src/components/Highlight/index.ts +2 -0
  447. package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
  448. package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
  449. package/src/components/HighlightedText/HighlightedText.tsx +50 -0
  450. package/src/components/HighlightedText/highlightRanges.ts +44 -0
  451. package/src/components/HighlightedText/index.ts +2 -0
  452. package/src/components/IconPicker/IconPicker.module.scss +175 -0
  453. package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
  454. package/src/components/IconPicker/IconPicker.tsx +629 -0
  455. package/src/components/IconPicker/index.ts +9 -0
  456. package/src/components/IconTile/IconTile.module.scss +57 -0
  457. package/src/components/IconTile/IconTile.tokens.scss +16 -0
  458. package/src/components/IconTile/IconTile.tsx +91 -0
  459. package/src/components/IconTile/index.ts +2 -0
  460. package/src/components/Image/Image.module.scss +266 -0
  461. package/src/components/Image/Image.tokens.scss +55 -0
  462. package/src/components/Image/Image.tsx +342 -0
  463. package/src/components/Image/index.ts +2 -0
  464. package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
  465. package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
  466. package/src/components/ImageCrop/ImageCrop.tsx +542 -0
  467. package/src/components/ImageCrop/cropGeometry.ts +120 -0
  468. package/src/components/ImageCrop/extractCropBlob.ts +140 -0
  469. package/src/components/ImageCrop/index.ts +11 -0
  470. package/src/components/ImageCrop/useCropPreview.ts +161 -0
  471. package/src/components/Indent/Indent.module.scss +33 -0
  472. package/src/components/Indent/Indent.tokens.scss +10 -0
  473. package/src/components/Indent/Indent.tsx +46 -0
  474. package/src/components/Indent/index.ts +2 -0
  475. package/src/components/Input/Input.module.scss +99 -0
  476. package/src/components/Input/Input.tokens.scss +54 -0
  477. package/src/components/Input/Input.tsx +105 -0
  478. package/src/components/Input/Suggestions.tsx +260 -0
  479. package/src/components/Input/index.ts +2 -0
  480. package/src/components/Kanban/Kanban.module.scss +39 -0
  481. package/src/components/Kanban/Kanban.tokens.scss +15 -0
  482. package/src/components/Kanban/Kanban.tsx +951 -0
  483. package/src/components/Kanban/index.ts +7 -0
  484. package/src/components/Kbd/Kbd.module.scss +47 -0
  485. package/src/components/Kbd/Kbd.tokens.scss +26 -0
  486. package/src/components/Kbd/Kbd.tsx +73 -0
  487. package/src/components/Kbd/index.ts +2 -0
  488. package/src/components/Lightbox/Lightbox.module.scss +283 -0
  489. package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
  490. package/src/components/Lightbox/Lightbox.tsx +506 -0
  491. package/src/components/Lightbox/index.ts +2 -0
  492. package/src/components/Link/Link.module.scss +78 -0
  493. package/src/components/Link/Link.tokens.scss +28 -0
  494. package/src/components/Link/Link.tsx +114 -0
  495. package/src/components/Link/index.ts +2 -0
  496. package/src/components/LinkCard/LinkCard.module.scss +92 -0
  497. package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
  498. package/src/components/LinkCard/LinkCard.tsx +72 -0
  499. package/src/components/LinkCard/index.ts +2 -0
  500. package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
  501. package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
  502. package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
  503. package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
  504. package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
  505. package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
  506. package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
  507. package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
  508. package/src/components/LiquidEditor/index.ts +7 -0
  509. package/src/components/LiquidEditor/liquidFilters.ts +23 -0
  510. package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
  511. package/src/components/LiquidEditor/types.ts +101 -0
  512. package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
  513. package/src/components/List/List.module.scss +105 -0
  514. package/src/components/List/List.tokens.scss +42 -0
  515. package/src/components/List/List.tsx +124 -0
  516. package/src/components/List/index.ts +9 -0
  517. package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
  518. package/src/components/LiveRegion/LiveRegion.tsx +116 -0
  519. package/src/components/LiveRegion/index.ts +2 -0
  520. package/src/components/Logo/Logo.module.scss +139 -0
  521. package/src/components/Logo/Logo.tokens.scss +14 -0
  522. package/src/components/Logo/Logo.tsx +126 -0
  523. package/src/components/Logo/index.ts +2 -0
  524. package/src/components/Masonry/Masonry.module.scss +42 -0
  525. package/src/components/Masonry/Masonry.tokens.scss +8 -0
  526. package/src/components/Masonry/Masonry.tsx +136 -0
  527. package/src/components/Masonry/index.ts +2 -0
  528. package/src/components/Masonry/masonryUtils.ts +42 -0
  529. package/src/components/MediaTile/MediaTile.module.scss +183 -0
  530. package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
  531. package/src/components/MediaTile/MediaTile.tsx +208 -0
  532. package/src/components/MediaTile/index.ts +8 -0
  533. package/src/components/Modal/Body.tsx +27 -0
  534. package/src/components/Modal/Close.tsx +45 -0
  535. package/src/components/Modal/Content.tsx +98 -0
  536. package/src/components/Modal/Footer.tsx +28 -0
  537. package/src/components/Modal/Header.tsx +51 -0
  538. package/src/components/Modal/Modal.module.scss +262 -0
  539. package/src/components/Modal/Modal.tokens.scss +50 -0
  540. package/src/components/Modal/Modal.tsx +23 -0
  541. package/src/components/Modal/ModalRoot.tsx +299 -0
  542. package/src/components/Modal/Overlay.tsx +101 -0
  543. package/src/components/Modal/context.ts +60 -0
  544. package/src/components/Modal/index.ts +11 -0
  545. package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
  546. package/src/components/MoneyInput/MoneyInput.tsx +433 -0
  547. package/src/components/MoneyInput/index.ts +2 -0
  548. package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
  549. package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
  550. package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
  551. package/src/components/OptionsPicker/index.ts +9 -0
  552. package/src/components/OtpInput/OtpInput.module.scss +69 -0
  553. package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
  554. package/src/components/OtpInput/OtpInput.tsx +368 -0
  555. package/src/components/OtpInput/index.ts +2 -0
  556. package/src/components/Page/Page.module.scss +30 -0
  557. package/src/components/Page/Page.tokens.scss +11 -0
  558. package/src/components/Page/Page.tsx +53 -0
  559. package/src/components/Page/index.ts +2 -0
  560. package/src/components/PageHeader/PageHeader.module.scss +197 -0
  561. package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
  562. package/src/components/PageHeader/PageHeader.tsx +310 -0
  563. package/src/components/PageHeader/index.ts +20 -0
  564. package/src/components/Pagination/Pagination.module.scss +117 -0
  565. package/src/components/Pagination/Pagination.tokens.scss +54 -0
  566. package/src/components/Pagination/Pagination.tsx +165 -0
  567. package/src/components/Pagination/index.ts +4 -0
  568. package/src/components/Pagination/paginationRange.ts +72 -0
  569. package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
  570. package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
  571. package/src/components/PasswordInput/PasswordInput.tsx +210 -0
  572. package/src/components/PasswordInput/index.ts +2 -0
  573. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
  574. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
  575. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
  576. package/src/components/PasswordStrengthMeter/index.ts +2 -0
  577. package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
  578. package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
  579. package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
  580. package/src/components/PersonDisplay/index.ts +10 -0
  581. package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
  582. package/src/components/PhoneInput/PhoneInput.tsx +271 -0
  583. package/src/components/PhoneInput/index.ts +4 -0
  584. package/src/components/PhoneInput/phone.ts +128 -0
  585. package/src/components/PillMenu/PillMenu.module.scss +117 -0
  586. package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
  587. package/src/components/PillMenu/PillMenu.tsx +324 -0
  588. package/src/components/PillMenu/index.ts +2 -0
  589. package/src/components/Popover/Anchor.tsx +37 -0
  590. package/src/components/Popover/Close.tsx +45 -0
  591. package/src/components/Popover/Content.tsx +213 -0
  592. package/src/components/Popover/Heading.tsx +33 -0
  593. package/src/components/Popover/Popover.module.scss +177 -0
  594. package/src/components/Popover/Popover.tokens.scss +22 -0
  595. package/src/components/Popover/Popover.tsx +23 -0
  596. package/src/components/Popover/PopoverRoot.tsx +75 -0
  597. package/src/components/Popover/Trigger.tsx +86 -0
  598. package/src/components/Popover/context.ts +22 -0
  599. package/src/components/Popover/index.ts +7 -0
  600. package/src/components/Progress/Progress.module.scss +110 -0
  601. package/src/components/Progress/Progress.tokens.scss +44 -0
  602. package/src/components/Progress/Progress.tsx +129 -0
  603. package/src/components/Progress/index.ts +2 -0
  604. package/src/components/QrCode/QrCode.module.scss +97 -0
  605. package/src/components/QrCode/QrCode.tokens.scss +17 -0
  606. package/src/components/QrCode/QrCode.tsx +233 -0
  607. package/src/components/QrCode/index.ts +2 -0
  608. package/src/components/QrCode/qr.ts +161 -0
  609. package/src/components/Radio/Radio.module.scss +175 -0
  610. package/src/components/Radio/Radio.tokens.scss +59 -0
  611. package/src/components/Radio/Radio.tsx +127 -0
  612. package/src/components/Radio/RadioGroup.module.scss +42 -0
  613. package/src/components/Radio/RadioGroup.tsx +120 -0
  614. package/src/components/Radio/RadioGroupContext.tsx +30 -0
  615. package/src/components/Radio/index.ts +4 -0
  616. package/src/components/Rail/Rail.module.scss +510 -0
  617. package/src/components/Rail/Rail.tokens.scss +92 -0
  618. package/src/components/Rail/Rail.tsx +287 -0
  619. package/src/components/Rail/RailCollapseToggle.tsx +57 -0
  620. package/src/components/Rail/RailFooter.tsx +17 -0
  621. package/src/components/Rail/RailGroup.tsx +728 -0
  622. package/src/components/Rail/RailGroupContext.ts +9 -0
  623. package/src/components/Rail/RailHeader.tsx +23 -0
  624. package/src/components/Rail/RailItem.tsx +119 -0
  625. package/src/components/Rail/RailSection.tsx +39 -0
  626. package/src/components/Rail/RailSpacer.tsx +19 -0
  627. package/src/components/Rail/index.ts +9 -0
  628. package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
  629. package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
  630. package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
  631. package/src/components/RelativeDateInput/index.ts +10 -0
  632. package/src/components/RelativeDateInput/relativeDate.ts +127 -0
  633. package/src/components/RichText/RichText.module.scss +5 -0
  634. package/src/components/RichText/RichText.tsx +70 -0
  635. package/src/components/RichText/RichTextAttachment.module.scss +82 -0
  636. package/src/components/RichText/RichTextAttachment.tsx +122 -0
  637. package/src/components/RichText/_prose.scss +79 -0
  638. package/src/components/RichText/attachmentIcon.tsx +24 -0
  639. package/src/components/RichText/engine/attachment.ts +154 -0
  640. package/src/components/RichText/engine/autolink.ts +64 -0
  641. package/src/components/RichText/engine/blockUnit.ts +174 -0
  642. package/src/components/RichText/engine/colorMarks.ts +85 -0
  643. package/src/components/RichText/engine/escape.ts +11 -0
  644. package/src/components/RichText/engine/fromHtml.ts +353 -0
  645. package/src/components/RichText/engine/fromMarkdown.ts +20 -0
  646. package/src/components/RichText/engine/inlines.ts +82 -0
  647. package/src/components/RichText/engine/listDepths.ts +32 -0
  648. package/src/components/RichText/engine/marks.ts +80 -0
  649. package/src/components/RichText/engine/mdToHtml.ts +178 -0
  650. package/src/components/RichText/engine/model.ts +157 -0
  651. package/src/components/RichText/engine/position.ts +118 -0
  652. package/src/components/RichText/engine/renderDoc.tsx +395 -0
  653. package/src/components/RichText/engine/renderLink.ts +15 -0
  654. package/src/components/RichText/engine/renderMention.ts +16 -0
  655. package/src/components/RichText/engine/safeHref.ts +22 -0
  656. package/src/components/RichText/engine/toHtml.ts +154 -0
  657. package/src/components/RichText/engine/toMarkdown.ts +97 -0
  658. package/src/components/RichText/engine/transforms.ts +434 -0
  659. package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
  660. package/src/components/RichText/index.ts +31 -0
  661. package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
  662. package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
  663. package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
  664. package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
  665. package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
  666. package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
  667. package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
  668. package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
  669. package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
  670. package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
  671. package/src/components/RichTextEditor/autolinkInput.ts +65 -0
  672. package/src/components/RichTextEditor/blockDrop.ts +9 -0
  673. package/src/components/RichTextEditor/blockReflow.ts +62 -0
  674. package/src/components/RichTextEditor/commands.ts +300 -0
  675. package/src/components/RichTextEditor/history.ts +93 -0
  676. package/src/components/RichTextEditor/icons.tsx +152 -0
  677. package/src/components/RichTextEditor/imageSize.ts +70 -0
  678. package/src/components/RichTextEditor/index.ts +5 -0
  679. package/src/components/RichTextEditor/input.ts +209 -0
  680. package/src/components/RichTextEditor/inputRules.ts +71 -0
  681. package/src/components/RichTextEditor/links.ts +103 -0
  682. package/src/components/RichTextEditor/mentionContext.ts +37 -0
  683. package/src/components/RichTextEditor/mentions.ts +28 -0
  684. package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
  685. package/src/components/RichTextEditor/selection.ts +415 -0
  686. package/src/components/RichTextEditor/shortcuts.ts +44 -0
  687. package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
  688. package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
  689. package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
  690. package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
  691. package/src/components/RichTextEditor/useMention.ts +226 -0
  692. package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
  693. package/src/components/RichTextEditor/useUpload.ts +246 -0
  694. package/src/components/Screen/Screen.module.scss +46 -0
  695. package/src/components/Screen/Screen.tokens.scss +20 -0
  696. package/src/components/Screen/Screen.tsx +97 -0
  697. package/src/components/Screen/index.ts +2 -0
  698. package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
  699. package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
  700. package/src/components/ScrollArea/ScrollArea.tsx +154 -0
  701. package/src/components/ScrollArea/index.ts +2 -0
  702. package/src/components/Select/Chip.tsx +45 -0
  703. package/src/components/Select/Empty.tsx +39 -0
  704. package/src/components/Select/Error.tsx +51 -0
  705. package/src/components/Select/HiddenInputs.tsx +44 -0
  706. package/src/components/Select/Listbox.tsx +557 -0
  707. package/src/components/Select/Loading.tsx +30 -0
  708. package/src/components/Select/Select.module.scss +512 -0
  709. package/src/components/Select/Select.tokens.scss +140 -0
  710. package/src/components/Select/Select.tsx +685 -0
  711. package/src/components/Select/Trigger.tsx +952 -0
  712. package/src/components/Select/context.ts +101 -0
  713. package/src/components/Select/emptyStateText.ts +19 -0
  714. package/src/components/Select/index.ts +9 -0
  715. package/src/components/Select/useSelectState.ts +157 -0
  716. package/src/components/Select/utils-types.ts +7 -0
  717. package/src/components/Select/utils.ts +122 -0
  718. package/src/components/SettingRow/SettingRow.module.scss +166 -0
  719. package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
  720. package/src/components/SettingRow/SettingRow.tsx +242 -0
  721. package/src/components/SettingRow/index.ts +7 -0
  722. package/src/components/Skeleton/Skeleton.module.scss +55 -0
  723. package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
  724. package/src/components/Skeleton/Skeleton.tsx +131 -0
  725. package/src/components/Skeleton/index.ts +4 -0
  726. package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
  727. package/src/components/Slider/Slider.module.scss +293 -0
  728. package/src/components/Slider/Slider.tokens.scss +98 -0
  729. package/src/components/Slider/Slider.tsx +624 -0
  730. package/src/components/Slider/index.ts +9 -0
  731. package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
  732. package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
  733. package/src/components/SlotGrid/SlotGrid.tsx +111 -0
  734. package/src/components/SlotGrid/index.ts +2 -0
  735. package/src/components/SocialButton/SocialButton.module.scss +4 -0
  736. package/src/components/SocialButton/SocialButton.tsx +40 -0
  737. package/src/components/SocialButton/index.ts +2 -0
  738. package/src/components/Sortable/Sortable.module.scss +177 -0
  739. package/src/components/Sortable/Sortable.tokens.scss +27 -0
  740. package/src/components/Sortable/Sortable.tsx +572 -0
  741. package/src/components/Sortable/containerAwareCollision.ts +125 -0
  742. package/src/components/Sortable/index.ts +13 -0
  743. package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
  744. package/src/components/SortableGroup/SortableGroup.tsx +315 -0
  745. package/src/components/SortableGroup/index.ts +4 -0
  746. package/src/components/SortableGroup/moveSortableItem.ts +39 -0
  747. package/src/components/Sparkline/Sparkline.module.scss +28 -0
  748. package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
  749. package/src/components/Sparkline/Sparkline.tsx +133 -0
  750. package/src/components/Sparkline/index.ts +2 -0
  751. package/src/components/Sparkline/sparklineModel.ts +119 -0
  752. package/src/components/Split/Split.module.scss +158 -0
  753. package/src/components/Split/Split.tokens.scss +10 -0
  754. package/src/components/Split/Split.tsx +231 -0
  755. package/src/components/Split/index.ts +2 -0
  756. package/src/components/Stack/Stack.module.scss +67 -0
  757. package/src/components/Stack/Stack.tokens.scss +11 -0
  758. package/src/components/Stack/Stack.tsx +100 -0
  759. package/src/components/Stack/index.ts +2 -0
  760. package/src/components/StagePath/StagePath.module.scss +255 -0
  761. package/src/components/StagePath/StagePath.tokens.scss +43 -0
  762. package/src/components/StagePath/StagePath.tsx +176 -0
  763. package/src/components/StagePath/index.ts +2 -0
  764. package/src/components/StatGroup/StatGroup.module.scss +6 -0
  765. package/src/components/StatGroup/StatGroup.tsx +70 -0
  766. package/src/components/StatGroup/StatGroupContext.ts +10 -0
  767. package/src/components/StatGroup/StatTile.module.scss +99 -0
  768. package/src/components/StatGroup/StatTile.tokens.scss +35 -0
  769. package/src/components/StatGroup/StatTile.tsx +143 -0
  770. package/src/components/StatGroup/index.ts +4 -0
  771. package/src/components/Sticky/Sticky.module.scss +98 -0
  772. package/src/components/Sticky/Sticky.tokens.scss +17 -0
  773. package/src/components/Sticky/Sticky.tsx +103 -0
  774. package/src/components/Sticky/index.ts +2 -0
  775. package/src/components/Switch/Switch.module.scss +182 -0
  776. package/src/components/Switch/Switch.tokens.scss +59 -0
  777. package/src/components/Switch/Switch.tsx +214 -0
  778. package/src/components/Switch/index.ts +2 -0
  779. package/src/components/Table/Table.module.scss +308 -0
  780. package/src/components/Table/Table.tokens.scss +79 -0
  781. package/src/components/Table/Table.tsx +381 -0
  782. package/src/components/Table/index.ts +15 -0
  783. package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
  784. package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
  785. package/src/components/TableOfContents/TableOfContents.tsx +192 -0
  786. package/src/components/TableOfContents/activeSection.ts +18 -0
  787. package/src/components/TableOfContents/index.ts +2 -0
  788. package/src/components/Tabs/Tabs.module.scss +359 -0
  789. package/src/components/Tabs/Tabs.tokens.scss +50 -0
  790. package/src/components/Tabs/Tabs.tsx +538 -0
  791. package/src/components/Tabs/index.ts +2 -0
  792. package/src/components/Text/Text.module.scss +115 -0
  793. package/src/components/Text/Text.tokens.scss +55 -0
  794. package/src/components/Text/Text.tsx +197 -0
  795. package/src/components/Text/index.ts +2 -0
  796. package/src/components/Textarea/Textarea.module.scss +94 -0
  797. package/src/components/Textarea/Textarea.tokens.scss +48 -0
  798. package/src/components/Textarea/Textarea.tsx +246 -0
  799. package/src/components/Textarea/index.ts +2 -0
  800. package/src/components/Thread/Thread.module.scss +161 -0
  801. package/src/components/Thread/Thread.tokens.scss +32 -0
  802. package/src/components/Thread/Thread.tsx +176 -0
  803. package/src/components/Thread/index.ts +2 -0
  804. package/src/components/TimeField/TimeField.module.scss +232 -0
  805. package/src/components/TimeField/TimeField.tsx +793 -0
  806. package/src/components/TimeField/index.ts +2 -0
  807. package/src/components/Timeline/Timeline.module.scss +58 -0
  808. package/src/components/Timeline/Timeline.tokens.scss +13 -0
  809. package/src/components/Timeline/Timeline.tsx +53 -0
  810. package/src/components/Timeline/index.ts +2 -0
  811. package/src/components/Title/Title.module.scss +84 -0
  812. package/src/components/Title/Title.tokens.scss +37 -0
  813. package/src/components/Title/Title.tsx +150 -0
  814. package/src/components/Title/index.ts +2 -0
  815. package/src/components/Toast/Toast.module.scss +299 -0
  816. package/src/components/Toast/Toast.tokens.scss +65 -0
  817. package/src/components/Toast/Toast.tsx +122 -0
  818. package/src/components/Toast/ToastViewport.tsx +166 -0
  819. package/src/components/Toast/api.ts +175 -0
  820. package/src/components/Toast/index.ts +5 -0
  821. package/src/components/Toast/store.ts +133 -0
  822. package/src/components/Toast/useToastTimer.ts +94 -0
  823. package/src/components/Tooltip/Tooltip.module.scss +99 -0
  824. package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
  825. package/src/components/Tooltip/Tooltip.tsx +341 -0
  826. package/src/components/Tooltip/index.ts +2 -0
  827. package/src/components/TopBar/TopBar.module.scss +235 -0
  828. package/src/components/TopBar/TopBar.tokens.scss +79 -0
  829. package/src/components/TopBar/TopBar.tsx +87 -0
  830. package/src/components/TopBar/TopBarEnd.tsx +20 -0
  831. package/src/components/TopBar/TopBarIconButton.tsx +86 -0
  832. package/src/components/TopBar/TopBarSearch.tsx +319 -0
  833. package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
  834. package/src/components/TopBar/TopBarStart.tsx +20 -0
  835. package/src/components/TopBar/index.ts +11 -0
  836. package/src/components/Tour/Spotlight.tsx +121 -0
  837. package/src/components/Tour/Tour.module.scss +210 -0
  838. package/src/components/Tour/Tour.tokens.scss +58 -0
  839. package/src/components/Tour/Tour.tsx +617 -0
  840. package/src/components/Tour/index.ts +2 -0
  841. package/src/components/Tour/useTourTarget.ts +115 -0
  842. package/src/components/TreeView/TreeView.module.scss +268 -0
  843. package/src/components/TreeView/TreeView.tokens.scss +36 -0
  844. package/src/components/TreeView/TreeView.tsx +536 -0
  845. package/src/components/TreeView/index.ts +3 -0
  846. package/src/components/TreeView/treeModel.ts +224 -0
  847. package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
  848. package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
  849. package/src/components/VisuallyHidden/index.ts +2 -0
  850. package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
  851. package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
  852. package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
  853. package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
  854. package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
  855. package/src/components/WidgetPreview/index.ts +2 -0
  856. package/src/components/_internal/Trend.tsx +27 -0
  857. package/src/components/_internal/choiceTile.scss +74 -0
  858. package/src/components/_internal/collapse.scss +10 -0
  859. package/src/components/_internal/collapse.ts +58 -0
  860. package/src/components/_internal/currency.ts +257 -0
  861. package/src/components/_internal/dragAnnouncements.ts +200 -0
  862. package/src/components/_internal/fieldWiring.ts +225 -0
  863. package/src/components/_internal/gridSpan.ts +54 -0
  864. package/src/components/_internal/isoDay.ts +35 -0
  865. package/src/components/_internal/letterKey.ts +26 -0
  866. package/src/components/_internal/overlay/focusRestore.ts +21 -0
  867. package/src/components/_internal/overlay/index.ts +12 -0
  868. package/src/components/_internal/overlay/tourHold.ts +23 -0
  869. package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
  870. package/src/components/_internal/overlay/useInOverlay.ts +81 -0
  871. package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
  872. package/src/components/_internal/overlay/useScrollLock.ts +112 -0
  873. package/src/components/_internal/refs.ts +48 -0
  874. package/src/components/_internal/statusColor.ts +26 -0
  875. package/src/components/_internal/timeUtils.ts +23 -0
  876. package/src/components/_internal/useAsyncOptions.ts +145 -0
  877. package/src/components/_internal/useClippedTooltip.ts +50 -0
  878. package/src/components/_internal/useControllableState.ts +50 -0
  879. package/src/components.manifest.json +1141 -0
  880. package/src/hooks/useBelowBreakpoint.ts +58 -0
  881. package/src/i18n/I18nProvider.tsx +52 -0
  882. package/src/i18n/LocaleProvider.tsx +17 -0
  883. package/src/i18n/en.ts +648 -0
  884. package/src/i18n/format.ts +71 -0
  885. package/src/i18n/index.ts +13 -0
  886. package/src/i18n/messages.ts +1275 -0
  887. package/src/i18n/ru.ts +677 -0
  888. package/src/i18n/useLocale.ts +19 -0
  889. package/src/i18n/useTranslation.ts +58 -0
  890. package/src/index.ts +913 -0
  891. package/src/palette/index.ts +2 -0
  892. package/src/palette/palette.ts +108 -0
  893. package/src/styles/dark.scss +4 -0
  894. package/src/styles/global.scss +7 -0
  895. package/src/styles/mixins.scss +143 -0
  896. package/src/styles/reset.scss +78 -0
  897. package/src/styles/tokens.scss +18 -0
  898. package/src/styles/typography.scss +44 -0
@@ -0,0 +1,415 @@
1
+ // selection.ts — map between the contentEditable DOM and model positions. All
2
+ // functions take the editable root element; block elements carry `data-block-id`.
3
+ import type { Point, Range } from '../RichText/engine/model';
4
+
5
+ /** Selector + predicate for atomic inline widgets (renderLink / renderMention
6
+ * substitutions): contentEditable=false nodes whose display text may differ from
7
+ * the `data-len` MODEL length they represent. */
8
+ const ATOMIC_WIDGET_SELECTOR = '[data-rich-link],[data-rich-mention]';
9
+ function isAtomicWidget(el: HTMLElement): boolean {
10
+ return el.hasAttribute('data-rich-link') || el.hasAttribute('data-rich-mention');
11
+ }
12
+
13
+ /** The MODEL length an atomic widget (`[data-rich-link]` / `[data-rich-mention]`)
14
+ * represents. Falls back to its display-text length if `data-len` is
15
+ * missing/non-numeric (so a malformed widget degrades gracefully instead of
16
+ * poisoning the offset math with NaN). */
17
+ function widgetLen(w: HTMLElement): number {
18
+ const n = Number(w.dataset.len);
19
+ return Number.isFinite(n) ? n : (w.textContent?.length ?? 0);
20
+ }
21
+
22
+ function blockElementFor(root: HTMLElement, node: Node): HTMLElement | null {
23
+ let el: Node | null = node.nodeType === Node.TEXT_NODE ? node.parentNode : node;
24
+ while (el && el !== root) {
25
+ if (el instanceof HTMLElement && el.hasAttribute('data-block-id')) return el;
26
+ el = el.parentNode;
27
+ }
28
+ return null;
29
+ }
30
+
31
+ /**
32
+ * A void attachment block element (`<figure data-block-id>`), or null. The
33
+ * `data-block-id` guard is load-bearing: callers rely on it to safely read the id.
34
+ * In editable mode renderDoc emits `<figure>` ONLY for attachment blocks and always
35
+ * stamps `data-block-id`, so every `data-block-id` figure in the editor is an
36
+ * attachment — the tag + attribute check is sufficient.
37
+ */
38
+ function figureBlock(node: Node | null | undefined): HTMLElement | null {
39
+ return node instanceof HTMLElement &&
40
+ node.tagName === 'FIGURE' &&
41
+ node.hasAttribute('data-block-id')
42
+ ? node
43
+ : null;
44
+ }
45
+
46
+ /** The first/last block element at or inside a root-level child node — the node
47
+ * itself when it IS a block, else its first/last `[data-block-id]` descendant
48
+ * (a `<ul>`/`<ol>` wrapper contains its `<li data-block-id>` items). Null for
49
+ * text/absent nodes. */
50
+ function blockWithin(node: Node | undefined, which: 'first' | 'last'): HTMLElement | null {
51
+ if (!(node instanceof HTMLElement)) return null;
52
+ if (node.hasAttribute('data-block-id')) return node;
53
+ const all = node.querySelectorAll<HTMLElement>('[data-block-id]');
54
+ return all.length > 0 ? all[which === 'first' ? 0 : all.length - 1] : null;
55
+ }
56
+
57
+ /**
58
+ * Character offset within `blockEl` of the DOM position `(node, offset)`. Works
59
+ * for both text-node boundaries (offset = char index) and element-node
60
+ * boundaries (offset = child index, e.g. a caret at an inline-element edge,
61
+ * after a `<br>`, or a word/line selection) — the browser Selection API
62
+ * produces both. Measured as the length of the text between the block start and
63
+ * the point via a DOM Range, which counts only character data (so `<br>`,
64
+ * empty blocks, and nested mark spans are all handled correctly).
65
+ *
66
+ * Atomic widgets (`[data-rich-link]` / `[data-rich-mention]`) are corrected for:
67
+ * such a widget renders DISPLAY text (e.g. "#1 Task") but represents `data-len`
68
+ * MODEL chars (e.g. the URL it links). `range.toString()` counts the display
69
+ * text, so for every widget that lies fully before the range end we add
70
+ * `data-len - displayLength`. When a block contains no atomic widget the
71
+ * correction loop runs zero times, so this is an exact no-op for ordinary content.
72
+ */
73
+ function offsetWithinBlock(blockEl: HTMLElement, node: Node, offset: number): number {
74
+ const doc = blockEl.ownerDocument;
75
+ const range = doc.createRange();
76
+ range.setStart(blockEl, 0);
77
+ try {
78
+ range.setEnd(node, offset);
79
+ } catch {
80
+ return 0; // node not inside blockEl (shouldn't happen) → block start
81
+ }
82
+ let len = range.toString().length;
83
+ for (const w of blockEl.querySelectorAll<HTMLElement>(ATOMIC_WIDGET_SELECTOR)) {
84
+ // The widget's display text is included in `len` iff our range end is at or
85
+ // past the point immediately AFTER the widget. Compare our range's END
86
+ // boundary against a collapsed range positioned just after the widget:
87
+ // compareBoundaryPoints(END_TO_END, afterW) returns where our END sits
88
+ // relative to afterW's (collapsed) boundary — >= 0 means our end is at/after
89
+ // the point just past the widget, so the whole widget falls within
90
+ // [blockStart, (node,offset)] and we replace its display length with data-len.
91
+ // (END_TO_END, not END_TO_START: the latter compares against afterW's START
92
+ // and mis-classifies the exact-boundary case in jsdom.)
93
+ const afterW = doc.createRange();
94
+ afterW.setStartAfter(w);
95
+ afterW.collapse(true);
96
+ if (range.compareBoundaryPoints(Range.END_TO_END, afterW) >= 0) {
97
+ const declared = widgetLen(w);
98
+ const shown = w.textContent?.length ?? 0;
99
+ len += declared - shown;
100
+ }
101
+ }
102
+ return len;
103
+ }
104
+
105
+ /**
106
+ * Map a DOM `(node, offset)` to a model `Point`, or `null` if outside any block.
107
+ *
108
+ * @param root - The contentEditable root element.
109
+ * @param node - The DOM node from a `Selection` or `Range` boundary.
110
+ * @param offset - Character offset within `node` (for text nodes) or child index
111
+ * (for element nodes, as the browser Selection API may return).
112
+ * @returns The model `Point`, or `null` when `node` is not inside a block
113
+ * element with a `data-block-id` attribute.
114
+ */
115
+ export function pointFromDom(root: HTMLElement, node: Node, offset: number): Point | null {
116
+ // Root-level caret (between blocks): if it sits at the boundary of a void
117
+ // figure, resolve to that void's {id, 0}. (A void can't host an interior caret,
118
+ // so the browser anchors the selection on the root around it.)
119
+ if (node === root) {
120
+ const kids = root.childNodes; // root Selection offsets count ALL child nodes
121
+ // Prefer the figure just AFTER the caret (caret-before-next-node), else the
122
+ // one just before it. `kids[-1]` (offset 0) is undefined → figureBlock null.
123
+ const fig = figureBlock(kids[offset]) ?? figureBlock(kids[offset - 1]);
124
+ if (fig) return { blockId: fig.getAttribute('data-block-id')!, offset: 0 };
125
+ }
126
+ const blockEl = blockElementFor(root, node);
127
+ if (blockEl) {
128
+ // A void figure block has no text — its only position is offset 0. (A caret on a
129
+ // figure descendant ascends to the figure via blockElementFor.)
130
+ if (blockEl.tagName === 'FIGURE') {
131
+ return { blockId: blockEl.getAttribute('data-block-id')!, offset: 0 };
132
+ }
133
+ return {
134
+ blockId: blockEl.getAttribute('data-block-id')!,
135
+ offset: offsetWithinBlock(blockEl, node, offset),
136
+ };
137
+ }
138
+ // Container-level caret: an element inside the editor with no block ancestor —
139
+ // the root itself or a <ul>/<ol> list wrapper (the only elements renderDoc puts
140
+ // between root and blocks). This happens when the block the selection lived in
141
+ // is removed from the DOM — e.g. a controlled external value replacement
142
+ // (parent setDoc(emptyDoc())) swaps the block elements, and the DOM collapses
143
+ // the live selection boundary to (container, childIndex). Resolve to the start
144
+ // of the next block, else the end of the previous one. Returning null here
145
+ // would make readSelection null, and the beforeinput handler would cede the
146
+ // keystroke to the browser — which then mutates the contentEditable DOM
147
+ // outside the model (raw text over the re-rendered content, onChange
148
+ // stalled). See #321.
149
+ if (node instanceof HTMLElement && (node === root || root.contains(node))) {
150
+ const kids = node.childNodes;
151
+ const next = blockWithin(kids[offset], 'first');
152
+ if (next) return { blockId: next.getAttribute('data-block-id')!, offset: 0 };
153
+ const prev = blockWithin(kids[offset - 1], 'last');
154
+ if (prev) {
155
+ // A figure here is unreachable (root-adjacent figures are caught by the
156
+ // figureBlock check above; figures never nest in list wrappers), so the
157
+ // end offset is always the block's widget-corrected full model length.
158
+ return {
159
+ blockId: prev.getAttribute('data-block-id')!,
160
+ offset: offsetWithinBlock(prev, prev, prev.childNodes.length),
161
+ };
162
+ }
163
+ }
164
+ return null;
165
+ }
166
+
167
+ /**
168
+ * Map a model `Point` to a DOM `{ node, offset }` inside the editable root.
169
+ *
170
+ * @param root - The contentEditable root element.
171
+ * @param point - The model position to locate in the DOM.
172
+ * @returns `{ node, offset }` suitable for `Range.setStart`/`setEnd`, or `null`
173
+ * when the block is not found in the DOM (e.g. after an async re-render).
174
+ */
175
+ export function pointToDom(root: HTMLElement, point: Point): { node: Node; offset: number } | null {
176
+ const blockEl = root.querySelector<HTMLElement>(`[data-block-id="${CSS.escape(point.blockId)}"]`);
177
+ if (!blockEl) return null;
178
+ // Void figure: the caret can't go inside — return a position just before it in
179
+ // its parent (the editable root), so the browser shows an edge caret.
180
+ if (blockEl.tagName === 'FIGURE') {
181
+ const parent = blockEl.parentNode!;
182
+ const index = Array.prototype.indexOf.call(parent.childNodes, blockEl);
183
+ return { node: parent, offset: index };
184
+ }
185
+ // Walk TEXT nodes and atomic widgets (`[data-rich-link]` / `[data-rich-mention]`),
186
+ // accumulating model length: text → its char length, widget → `data-len` (NOT its
187
+ // display text; we never descend into a widget). A widget is contenteditable=false,
188
+ // so the caret can only sit adjacent to it — when `remaining` lands at a widget we
189
+ // return a point in the widget's PARENT at the widget's child index (before)
190
+ // or +1 (after), never inside it. With no widgets present this behaves exactly
191
+ // like the previous text-only TreeWalker (FILTER_SKIP descends into mark spans).
192
+ const walker = blockEl.ownerDocument.createTreeWalker(
193
+ blockEl,
194
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
195
+ {
196
+ acceptNode(n) {
197
+ if (n instanceof HTMLElement && isAtomicWidget(n)) return NodeFilter.FILTER_ACCEPT; // the widget itself, atomic
198
+ // Reject the widget's contents so the walk treats it as one opaque unit
199
+ // (a TreeWalker descends into an ACCEPTED element, so we must REJECT its
200
+ // descendants — REJECT skips the node AND its subtree, unlike SKIP).
201
+ let p: Node | null = n.parentNode;
202
+ while (p && p !== blockEl) {
203
+ if (p instanceof HTMLElement && isAtomicWidget(p)) return NodeFilter.FILTER_REJECT;
204
+ p = p.parentNode;
205
+ }
206
+ if (n.nodeType === Node.TEXT_NODE) return NodeFilter.FILTER_ACCEPT;
207
+ return NodeFilter.FILTER_SKIP; // descend into ordinary inline elements
208
+ },
209
+ },
210
+ );
211
+ let remaining = point.offset;
212
+ let last: Text | null = null;
213
+ let n = walker.nextNode();
214
+ while (n) {
215
+ if (n.nodeType === Node.TEXT_NODE) {
216
+ const t = n as Text;
217
+ const len = t.textContent?.length ?? 0;
218
+ if (remaining <= len) return { node: t, offset: remaining };
219
+ remaining -= len;
220
+ last = t;
221
+ } else {
222
+ const w = n as HTMLElement;
223
+ const parent = w.parentNode!;
224
+ const index = Array.prototype.indexOf.call(parent.childNodes, w);
225
+ const declared = widgetLen(w);
226
+ // At the widget's leading edge → caret just before it.
227
+ if (remaining <= 0) return { node: parent, offset: index };
228
+ // Inside the widget's model span (incl. its trailing edge) → caret after it.
229
+ if (remaining <= declared) return { node: parent, offset: index + 1 };
230
+ remaining -= declared;
231
+ last = null; // can't anchor a leftover offset to a non-text widget
232
+ }
233
+ n = walker.nextNode();
234
+ }
235
+ if (last) return { node: last, offset: last.textContent?.length ?? 0 };
236
+ return { node: blockEl, offset: 0 }; // empty block (only a <br>)
237
+ }
238
+
239
+ /**
240
+ * Read the current DOM selection as a model `Range`, or `null` if not inside `root`.
241
+ *
242
+ * @param root - The contentEditable root element.
243
+ * @returns The model `Range`, or `null` when the selection is outside the root
244
+ * or the document has no selection.
245
+ */
246
+ export function readSelection(root: HTMLElement): Range | null {
247
+ const sel = root.ownerDocument.getSelection();
248
+ if (!sel || sel.rangeCount === 0 || !sel.anchorNode || !sel.focusNode) return null;
249
+ if (!root.contains(sel.anchorNode) || !root.contains(sel.focusNode)) return null;
250
+ const anchor = pointFromDom(root, sel.anchorNode, sel.anchorOffset);
251
+ const focus = pointFromDom(root, sel.focusNode, sel.focusOffset);
252
+ return anchor && focus ? { anchor, focus } : null;
253
+ }
254
+
255
+ /**
256
+ * Set the DOM selection from a model `Range`.
257
+ *
258
+ * @param root - The contentEditable root element.
259
+ * @param range - The model range to restore. When anchor === focus, sets a
260
+ * collapsed caret; otherwise extends the selection directionally.
261
+ */
262
+ export function writeSelection(root: HTMLElement, range: Range): void {
263
+ const sel = root.ownerDocument.getSelection();
264
+ if (!sel) return;
265
+ const a = pointToDom(root, range.anchor);
266
+ const f = pointToDom(root, range.focus);
267
+ if (!a || !f) return;
268
+ const domRange = root.ownerDocument.createRange();
269
+ domRange.setStart(a.node, a.offset);
270
+ domRange.setEnd(a.node, a.offset);
271
+ sel.removeAllRanges();
272
+ sel.addRange(domRange);
273
+ try {
274
+ sel.extend(f.node, f.offset);
275
+ } catch {
276
+ // some environments (jsdom) have a partial Selection — collapsed caret is fine
277
+ }
278
+ }
279
+
280
+ /** A viewport rect (subset of DOMRect) used to anchor floating UI to a selection. */
281
+ export type Rect = { top: number; left: number; height: number; width: number };
282
+
283
+ /**
284
+ * The viewport rect to anchor floating UI (the link editor) to the current DOM
285
+ * selection. Prefers the selection's own rect; when that's degenerate — a collapsed
286
+ * caret in an EMPTY block returns an all-zero rect — it falls back to the caret's
287
+ * BLOCK element (the active line), so an anchored popover opens beside that line.
288
+ * Only if there's no block (caret directly in root) does it fall back to `root`.
289
+ * (The old root fallback used the editor's full height, which dropped the link
290
+ * popover below the whole document — visible via `toolbar="auto"` + Link on an
291
+ * empty composer.)
292
+ */
293
+ export function selectionRect(root: HTMLElement): Rect {
294
+ const sel = typeof window !== 'undefined' ? window.getSelection() : null;
295
+ if (sel && sel.rangeCount > 0) {
296
+ const range = sel.getRangeAt(0);
297
+ let r: DOMRect | null = null;
298
+ try {
299
+ r = range.getBoundingClientRect();
300
+ } catch {
301
+ // jsdom does not implement Range.getBoundingClientRect — fall through.
302
+ }
303
+ if (r && (r.width || r.height || r.top || r.left)) {
304
+ return { top: r.top, left: r.left, width: r.width, height: r.height };
305
+ }
306
+ // Degenerate selection rect (e.g. collapsed caret in an empty block). Anchor to
307
+ // the caret's block element (the active line), not the whole editor.
308
+ const blockEl = blockElementFor(root, range.startContainer);
309
+ if (blockEl) {
310
+ const b = blockEl.getBoundingClientRect();
311
+ return { top: b.top, left: b.left, width: b.width, height: b.height };
312
+ }
313
+ }
314
+ const rr = root.getBoundingClientRect();
315
+ return { top: rr.top, left: rr.left, width: 0, height: rr.height };
316
+ }
317
+
318
+ /**
319
+ * The viewport rect of a MODEL range, re-derived from the DOM live. Unlike
320
+ * `selectionRect` (which reads the window selection), this is independent of the
321
+ * current selection — so a popover that has stolen focus (the link editor) can
322
+ * still track its original anchor line on scroll by re-measuring on each
323
+ * reposition. Returns null when the range can't be mapped to the DOM. Falls back
324
+ * to the anchor's block element (the active line) when the range rect is
325
+ * degenerate (a collapsed caret in an empty block).
326
+ */
327
+ export function rangeRect(root: HTMLElement, range: Range): Rect | null {
328
+ const a = pointToDom(root, range.anchor);
329
+ const f = pointToDom(root, range.focus);
330
+ if (!a || !f) return null;
331
+ // Order the two boundary points by document position before building the DOM
332
+ // range. A backward (right-to-left) model selection has its anchor AFTER its
333
+ // focus; feeding setStart(anchor)/setEnd(focus) straight through would not throw —
334
+ // the DOM clamps end-before-start to a COLLAPSED range, which measures as a zero
335
+ // rect and would wrongly degrade to the block fallback below. Pick start = the
336
+ // earlier point so the span rect is correct regardless of selection direction.
337
+ const startFirst =
338
+ a.node === f.node
339
+ ? a.offset <= f.offset
340
+ : !!(a.node.compareDocumentPosition(f.node) & Node.DOCUMENT_POSITION_FOLLOWING);
341
+ const [s, e] = startFirst ? [a, f] : [f, a];
342
+ const domRange = root.ownerDocument.createRange();
343
+ try {
344
+ domRange.setStart(s.node, s.offset);
345
+ domRange.setEnd(e.node, e.offset);
346
+ } catch {
347
+ return null;
348
+ }
349
+ let r: DOMRect | null = null;
350
+ try {
351
+ r = domRange.getBoundingClientRect();
352
+ } catch {
353
+ // jsdom does not implement Range.getBoundingClientRect — fall through.
354
+ }
355
+ if (r && (r.width || r.height || r.top || r.left)) {
356
+ return { top: r.top, left: r.left, width: r.width, height: r.height };
357
+ }
358
+ const blockEl = blockElementFor(root, a.node);
359
+ if (blockEl) {
360
+ const b = blockEl.getBoundingClientRect();
361
+ return { top: b.top, left: b.left, width: b.width, height: b.height };
362
+ }
363
+ return null;
364
+ }
365
+
366
+ /**
367
+ * Which side of a void block's figure the native caret sits on, or null when it
368
+ * isn't beside/inside that figure. `inside` = the caret is WITHIN the
369
+ * `contentEditable=false` figure, where browsers fire no `beforeinput` (the
370
+ * editor must handle keys itself); otherwise it's a container-level caret next
371
+ * to the figure (e.g. where writeSelection parks it), which edits normally.
372
+ */
373
+ export function voidCaretSide(
374
+ root: HTMLElement,
375
+ blockId: string,
376
+ ): { side: 'before' | 'after'; inside: boolean } | null {
377
+ const sel = root.ownerDocument.getSelection();
378
+ const fig = figureBlock(
379
+ root.querySelector<HTMLElement>(`[data-block-id="${CSS.escape(blockId)}"]`),
380
+ );
381
+ const node = sel?.anchorNode;
382
+ if (!sel || !node || !fig) return null;
383
+ if (fig.contains(node)) {
384
+ // "Before" only at the very start of the figure: offset 0 on a node that is
385
+ // the first descendant chain of the figure (no content precedes it).
386
+ let before = sel.anchorOffset === 0;
387
+ for (let n: Node | null = node; before && n && n !== fig; n = n.parentNode) {
388
+ if (n.previousSibling) before = false;
389
+ }
390
+ return { side: before ? 'before' : 'after', inside: true };
391
+ }
392
+ const kids = node.childNodes;
393
+ if (kids[sel.anchorOffset] === fig) return { side: 'before', inside: false };
394
+ if (kids[sel.anchorOffset - 1] === fig) return { side: 'after', inside: false };
395
+ return null;
396
+ }
397
+
398
+ /**
399
+ * A block's OWN text as rendered in the DOM, in MODEL offsets: nested child
400
+ * blocks (a list item's sublist) are skipped and each atomic widget counts as
401
+ * `data-len` placeholder chars. Null when the block isn't rendered. Diffing two
402
+ * snapshots of it locates what an IME composition changed.
403
+ */
404
+ export function blockOwnText(root: HTMLElement, blockId: string): string | null {
405
+ const el = root.querySelector<HTMLElement>(`[data-block-id="${CSS.escape(blockId)}"]`);
406
+ if (!el) return null;
407
+ const walk = (n: Node): string => {
408
+ if (n.nodeType === Node.TEXT_NODE) return n.textContent ?? '';
409
+ if (!(n instanceof HTMLElement)) return '';
410
+ if (n !== el && n.hasAttribute('data-block-id')) return '';
411
+ if (isAtomicWidget(n)) return '\uFFFC'.repeat(widgetLen(n));
412
+ return Array.from(n.childNodes, walk).join('');
413
+ };
414
+ return walk(el);
415
+ }
@@ -0,0 +1,44 @@
1
+ // shortcuts.ts — map a keydown to the inline mark it toggles. `shortcutMark` is
2
+ // pure (key + modifiers → Mark | null); the editor reads it for both the
3
+ // selection toggle and the collapsed-caret pending-mark path.
4
+ import type { Mark } from '../RichText/engine/model';
5
+ import { isLetterKey } from '../_internal/letterKey';
6
+
7
+ /** The minimal keyboard-event shape the shortcut helpers read (matches `KeyboardEvent`). */
8
+ export interface ShortcutKey {
9
+ key: string;
10
+ /** Physical key — the fallback on non-Latin layouts (#654). */
11
+ code: string;
12
+ /** Alt/AltGr held — disables the `code` fallback (AltGr letters are typing). */
13
+ altKey?: boolean;
14
+ metaKey: boolean;
15
+ ctrlKey: boolean;
16
+ shiftKey: boolean;
17
+ }
18
+
19
+ /**
20
+ * Map a keyboard event (key + modifiers) to the inline mark it toggles, or
21
+ * `null` when the combination isn't a formatting shortcut. The single source of
22
+ * truth for the key→mark mapping — the editor reads it for both the selection
23
+ * toggle and the collapsed-caret pending-mark path. Pure: no DOM, no side
24
+ * effects.
25
+ *
26
+ * Handled shortcuts:
27
+ * - ⌘/Ctrl+B → bold
28
+ * - ⌘/Ctrl+I → italic
29
+ * - ⌘/Ctrl+U → underline
30
+ * - ⌘/Ctrl+⇧X → strike
31
+ *
32
+ * @example
33
+ * const mark = shortcutMark(e);
34
+ * if (mark) { e.preventDefault(); commit(toggleMark(doc, range, mark)); }
35
+ */
36
+ export function shortcutMark(e: ShortcutKey): Mark | null {
37
+ const mod = e.metaKey || e.ctrlKey;
38
+ if (!mod) return null;
39
+ if (isLetterKey(e, 'b') && !e.shiftKey) return { type: 'bold' };
40
+ if (isLetterKey(e, 'i') && !e.shiftKey) return { type: 'italic' };
41
+ if (isLetterKey(e, 'u') && !e.shiftKey) return { type: 'underline' };
42
+ if (isLetterKey(e, 'x') && e.shiftKey) return { type: 'strike' };
43
+ return null;
44
+ }
@@ -0,0 +1,50 @@
1
+ // useAnchoredFloating.ts — shared portal-overlay positioning for <RichTextEditor>.
2
+ // The link bubble, @-mention listbox, and attachment config popover all anchor a
3
+ // Floating UI virtual element to a (live) selection/figure rect — fixed strategy,
4
+ // flip + shift, auto-updating on scroll/resize. This collapses that duplicated
5
+ // scaffolding into one hook. Internal; NOT exported from the package.
6
+ import { useMemo } from 'react';
7
+ import { useFloating, autoUpdate, flip, shift, offset } from '@floating-ui/react-dom';
8
+ import type { Rect } from './selection';
9
+
10
+ /** Expand a `Rect` (top/left/width/height) into the full DOMRect shape Floating UI reads. */
11
+ function rectToDomRect(r: Rect): DOMRect {
12
+ return {
13
+ x: r.left,
14
+ y: r.top,
15
+ top: r.top,
16
+ left: r.left,
17
+ right: r.left + r.width,
18
+ bottom: r.top + r.height,
19
+ width: r.width,
20
+ height: r.height,
21
+ } as DOMRect;
22
+ }
23
+
24
+ /**
25
+ * Shared portal-overlay positioning: a Floating UI virtual element anchored to a
26
+ * (live) rect, fixed strategy + flip + shift, auto-updating on scroll/resize.
27
+ * Mirrors the link/mention/attachment overlays' anchoring in one place.
28
+ *
29
+ * `getAnchorRect`, when provided, is re-read on every reposition so the overlay
30
+ * tracks the selection line / figure on scroll (the static `anchorRect` is the
31
+ * fallback for the initial frame / when the live rect is unavailable). `opts.offset`
32
+ * sets the gap between anchor and overlay (defaults to 6).
33
+ */
34
+ export function useAnchoredFloating(
35
+ anchorRect: Rect,
36
+ getAnchorRect: (() => Rect | null) | undefined,
37
+ opts: { offset?: number } = {},
38
+ ) {
39
+ const virtualRef = useMemo(
40
+ () => ({ getBoundingClientRect: () => rectToDomRect(getAnchorRect?.() ?? anchorRect) }),
41
+ [anchorRect, getAnchorRect],
42
+ );
43
+ return useFloating({
44
+ placement: 'bottom-start',
45
+ strategy: 'fixed',
46
+ whileElementsMounted: autoUpdate,
47
+ middleware: [offset(opts.offset ?? 6), flip(), shift({ padding: 4 })],
48
+ elements: { reference: virtualRef },
49
+ });
50
+ }
@@ -0,0 +1,134 @@
1
+ import { useCallback, useState } from 'react';
2
+ import type { RichDoc, Range } from '../RichText/engine/model';
3
+ import type { EditKind } from './history';
4
+ import { collapsedRange } from '../RichText/engine/position';
5
+ import { updateAttachmentBlock, clearAttachmentFields } from '../RichText/engine/attachment';
6
+
7
+ interface UseAttachmentConfigArgs {
8
+ /** The editable root — read to refocus the editor on close. */
9
+ rootRef: React.RefObject<HTMLDivElement | null>;
10
+ /** The editor's commit path (history + onChange round-trip) for the
11
+ * non-live config edits (alt / align / width-reset). */
12
+ commit: (result: { doc: RichDoc; selection: Range }, kind?: EditKind) => void;
13
+ /** The editor-owned live-resize commit: records ONE coalescing `'resize'`
14
+ * history entry (whole drag = one undo step), writes NO pending selection (so
15
+ * the slider/handle keeps focus mid-drag), and chains off `liveDocRef`. The
16
+ * hook builds the resized doc and hands it here so the history coupling stays
17
+ * isolated in the editor. */
18
+ commitResizeLive: (doc: RichDoc) => void;
19
+ /** The synchronously-latest controlled doc (`() => latest.current.value`). */
20
+ getValue: () => RichDoc;
21
+ /** The synchronously-latest live doc (`() => liveDocRef.current`) — read by
22
+ * the live-resize handler so rapid moves chain off each other before React
23
+ * re-renders. */
24
+ getLiveDoc: () => RichDoc;
25
+ /** Mirror of the upload controller — `replace` swaps an attachment's file. */
26
+ uploaderRef: React.RefObject<{ replace: (id: string, file: File) => void }>;
27
+ }
28
+
29
+ /**
30
+ * The attachment-config cluster, extracted from `RichTextEditor`: owns the
31
+ * `configBlockId` open-state and the alt/align/width/width-reset/replace
32
+ * handlers for the `<RichTextAttachmentConfig>` popover. The editor keeps the
33
+ * popover JSX (it derives the configured block + anchor rect from render scope)
34
+ * and the live-resize history coupling (via the injected `commitResizeLive`);
35
+ * only the state + handlers live here.
36
+ *
37
+ * Config edits don't move the caret meaningfully (the popover holds focus), so
38
+ * each non-live commit pins a collapsed selection on the block. `onConfigWidth`
39
+ * is the LIVE-resize path (fires on every slider/handle move) — it builds the
40
+ * resized doc here and routes through `commitResizeLive`, NOT `commit`.
41
+ */
42
+ export function useAttachmentConfig({
43
+ rootRef,
44
+ commit,
45
+ commitResizeLive,
46
+ getValue,
47
+ getLiveDoc,
48
+ uploaderRef,
49
+ }: UseAttachmentConfigArgs) {
50
+ const [configBlockId, setConfigBlockId] = useState<string | null>(null);
51
+
52
+ // Open/close toggle `configBlockId`; close returns focus to the editor.
53
+ const onConfigOpen = useCallback((id: string) => setConfigBlockId(id), []);
54
+ const onConfigClose = useCallback(() => {
55
+ setConfigBlockId(null);
56
+ rootRef.current?.focus();
57
+ }, [rootRef]);
58
+
59
+ const onConfigAlt = useCallback(
60
+ (id: string, alt: string) => {
61
+ commit(
62
+ {
63
+ doc: updateAttachmentBlock(getValue(), id, { alt }),
64
+ selection: collapsedRange(id),
65
+ },
66
+ 'other',
67
+ );
68
+ },
69
+ [commit, getValue],
70
+ );
71
+ const onConfigAlign = useCallback(
72
+ (id: string, align: 'left' | 'center' | 'right') => {
73
+ commit(
74
+ {
75
+ doc: updateAttachmentBlock(getValue(), id, { align }),
76
+ selection: collapsedRange(id),
77
+ },
78
+ 'other',
79
+ );
80
+ },
81
+ [commit, getValue],
82
+ );
83
+ const onConfigWidth = useCallback(
84
+ (id: string, width: number) => {
85
+ // Live resize: fires on every slider/handle MOVE (not just the end) so the
86
+ // image tracks the control. Three deliberate choices vs a plain `commit`,
87
+ // all owned by the injected `commitResizeLive`:
88
+ // • Coalescing 'resize' kind → the whole drag is ONE undo step (reverting
89
+ // to the pre-drag width), instead of one per pixel.
90
+ // • `pendingSelectionRef` cleared (no caret placed) → the slider/handle
91
+ // keeps focus; a `writeSelection` into the editable would yank it mid-drag.
92
+ // • Reads `liveDocRef` (the synchronously-latest doc) so rapid moves that
93
+ // fire before React re-renders still chain off each other.
94
+ // Width only; clearing height lets the browser keep the aspect ratio.
95
+ let d = updateAttachmentBlock(getLiveDoc(), id, { width });
96
+ d = clearAttachmentFields(d, id, ['height']);
97
+ commitResizeLive(d);
98
+ },
99
+ [commitResizeLive, getLiveDoc],
100
+ );
101
+ const onConfigWidthReset = useCallback(
102
+ (id: string) => {
103
+ commit(
104
+ {
105
+ doc: clearAttachmentFields(getValue(), id, ['width', 'height']),
106
+ selection: collapsedRange(id),
107
+ },
108
+ 'other',
109
+ );
110
+ },
111
+ [commit, getValue],
112
+ );
113
+ const onConfigReplace = useCallback(
114
+ (id: string, file: File) => {
115
+ uploaderRef.current?.replace(id, file);
116
+ // The block flips to `status: 'uploading'`, which unmounts the popover (it
117
+ // only shows for `ready`). Clear config state too so it doesn't spontaneously
118
+ // reappear when the upload settles back to `ready`.
119
+ setConfigBlockId(null);
120
+ },
121
+ [uploaderRef],
122
+ );
123
+
124
+ return {
125
+ configBlockId,
126
+ onConfigOpen,
127
+ onConfigClose,
128
+ onConfigAlt,
129
+ onConfigAlign,
130
+ onConfigWidth,
131
+ onConfigWidthReset,
132
+ onConfigReplace,
133
+ };
134
+ }
@@ -0,0 +1,26 @@
1
+ // useDismissOnOutsidePointerDown.ts — shared "click outside to dismiss" for the
2
+ // <RichTextEditor> floating overlays (link bubble, attachment config popover).
3
+ // A capture-phase document pointerdown listener fires `onClose` when the press
4
+ // lands outside `ref`. Capture phase + pointerdown (not click) so the dismissal
5
+ // runs before the press can move/clear the editor selection. Internal; NOT
6
+ // exported from the package.
7
+ import { useEffect, type RefObject } from 'react';
8
+
9
+ /**
10
+ * Call `onClose` when a pointerdown lands outside the element referenced by `ref`.
11
+ * The listener is registered on `document` in the capture phase. `ref` is a stable
12
+ * `useRef` object, so the effect effectively re-subscribes only when `onClose`'s
13
+ * identity changes — matching the overlays' original `[onClose]`-keyed effects.
14
+ */
15
+ export function useDismissOnOutsidePointerDown(
16
+ ref: RefObject<HTMLElement | null>,
17
+ onClose: () => void,
18
+ ) {
19
+ useEffect(() => {
20
+ const onPointerDown = (e: PointerEvent) => {
21
+ if (ref.current && !ref.current.contains(e.target as Node)) onClose();
22
+ };
23
+ document.addEventListener('pointerdown', onPointerDown, true);
24
+ return () => document.removeEventListener('pointerdown', onPointerDown, true);
25
+ }, [ref, onClose]);
26
+ }