@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,129 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
2
+ import clsx from 'clsx';
3
+ import { useTranslation } from '../../i18n/useTranslation';
4
+ import styles from './Progress.module.scss';
5
+
6
+ /** Visual size — controls the track height. */
7
+ export type ProgressSize = 'sm' | 'md' | 'lg';
8
+
9
+ /** Color tone for the fill. Default `'default'` uses the accent color. */
10
+ export type ProgressTone = 'default' | 'success' | 'warning' | 'danger';
11
+
12
+ /** Label render mode. */
13
+ export type ProgressLabel = boolean | ReactNode;
14
+
15
+ export interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {
16
+ /**
17
+ * Current progress value. Omit (or pass `undefined`) to render the
18
+ * indeterminate animation.
19
+ *
20
+ * Two-channel behavior for out-of-range and degenerate values:
21
+ * - **Visual fill** is clamped to [0%, 100%]. Values outside [0, max]
22
+ * render at the nearest valid bound.
23
+ * - **ARIA `aria-valuenow`** reports the raw number — this is the right
24
+ * screen-reader behavior so consumer bugs (a value drifting past max)
25
+ * surface in audits and SR announcements.
26
+ *
27
+ * Degenerate inputs fall back to the indeterminate animation: `NaN`,
28
+ * `Infinity`, `-Infinity`, and the case where `max <= 0`. This is the
29
+ * common file-upload race condition (`bytes_uploaded / total_bytes`
30
+ * before `total_bytes` is known produces NaN).
31
+ */
32
+ value?: number;
33
+ /**
34
+ * Upper bound. Defaults to `100`. Consumers using fraction values
35
+ * (0.0–1.0) pass `max={1}`. Consumers tracking a count ("3 of 10")
36
+ * pass `max={10}`.
37
+ */
38
+ max?: number;
39
+ /**
40
+ * Track height.
41
+ * - `sm` — 4px (compact / inside form rows)
42
+ * - `md` — 8px (default)
43
+ * - `lg` — 12px (page-level emphasis)
44
+ */
45
+ size?: ProgressSize;
46
+ /**
47
+ * Fill color tone. Defaults to `'default'` (accent blue). Tone applies
48
+ * ONLY to determinate mode; indeterminate always uses the accent tone
49
+ * because state-color semantics don't apply to an unknown total.
50
+ * - `default` — `--color-accent`
51
+ * - `success` — `--color-success`
52
+ * - `warning` — `--color-warning-strong`
53
+ * - `danger` — `--color-danger`
54
+ */
55
+ tone?: ProgressTone;
56
+ /**
57
+ * Optional label rendered to the RIGHT of the bar.
58
+ * - `false` (default) — no label
59
+ * - `true` — render `{Math.round((value / max) * 100)}%` when determinate.
60
+ * Auto-suppressed when indeterminate (there's no percentage to show).
61
+ * - `ReactNode` — render the node as-is, in BOTH determinate and
62
+ * indeterminate modes. Consumers wanting "Loading…" text next to an
63
+ * indeterminate bar pass `label="Loading…"`.
64
+ */
65
+ label?: ProgressLabel;
66
+ }
67
+
68
+ const SIZE_CLASS: Record<ProgressSize, string> = {
69
+ sm: styles.sizeSm,
70
+ md: styles.sizeMd,
71
+ lg: styles.sizeLg,
72
+ };
73
+
74
+ const TONE_CLASS: Record<ProgressTone, string> = {
75
+ default: styles.toneDefault,
76
+ success: styles.toneSuccess,
77
+ warning: styles.toneWarning,
78
+ danger: styles.toneDanger,
79
+ };
80
+
81
+ /**
82
+ * Linear progress bar: determinate against `max`, or an indeterminate slide when `value` is omitted; `role="progressbar"` is locked.
83
+ * @see docs/components/Progress.md
84
+ */
85
+ export const Progress = forwardRef<HTMLDivElement, ProgressProps>(function Progress(
86
+ { value, max = 100, size = 'md', tone = 'default', label = false, className, ...rest },
87
+ ref,
88
+ ) {
89
+ // Determinate requires a finite numeric value AND a positive max. NaN /
90
+ // Infinity / max<=0 are silent consumer-bug paths (esp. file-upload divides
91
+ // bytes_uploaded / total_bytes before total_bytes is known → NaN). Fall
92
+ // back to the indeterminate animation rather than rendering a vanished bar
93
+ // or announcing "NaN percent" to screen readers.
94
+ const determinate = typeof value === 'number' && Number.isFinite(value) && max > 0;
95
+ const indeterminate = !determinate;
96
+ // VISUAL clamp only — ARIA reports the raw `value` via aria-valuenow below.
97
+ const percent = determinate ? Math.max(0, Math.min(100, (value / max) * 100)) : 0;
98
+ // Indeterminate has no aria-valuenow, so aria-valuetext is the only thing a
99
+ // screen reader has. Prefer the consumer's aria-label; the translated
100
+ // fallback is what it hears when there isn't one. This was hardcoded English
101
+ // in both progress components (#503).
102
+ const t = useTranslation();
103
+ const ariaLabel = rest['aria-label'];
104
+ const valuetext = indeterminate ? ariaLabel || t('progress.indeterminate') : undefined;
105
+
106
+ // {...rest} last so consumer overrides win (Pattern A).
107
+ return (
108
+ <div
109
+ ref={ref}
110
+ role="progressbar"
111
+ className={clsx(styles.progress, SIZE_CLASS[size], TONE_CLASS[tone], className)}
112
+ aria-valuemin={0}
113
+ aria-valuemax={max}
114
+ aria-valuenow={determinate ? value : undefined}
115
+ aria-valuetext={valuetext}
116
+ {...rest}
117
+ >
118
+ <div className={styles.track}>
119
+ <div
120
+ className={clsx(styles.fill, indeterminate && styles.indeterminate)}
121
+ style={determinate ? { width: `${percent}%` } : undefined}
122
+ />
123
+ </div>
124
+ {label !== false && !(label === true && indeterminate) && (
125
+ <span className={styles.label}>{label === true ? `${Math.round(percent)}%` : label}</span>
126
+ )}
127
+ </div>
128
+ );
129
+ });
@@ -0,0 +1,2 @@
1
+ export { Progress } from './Progress';
2
+ export type { ProgressProps, ProgressSize, ProgressTone, ProgressLabel } from './Progress';
@@ -0,0 +1,97 @@
1
+ @use '../../styles/mixins' as *;
2
+ @use './QrCode.tokens';
3
+
4
+ .root {
5
+ // Centres the painted frame, which is up to ONE MODULE narrower than the
6
+ // button once the symbol snaps to a whole number of device pixels per module
7
+ // — `side / dpr` CSS px, not a fraction of a pixel. The leftover shows as
8
+ // paper, reading as a slightly wider quiet zone.
9
+ display: flex;
10
+ justify-content: center;
11
+ width: 100%;
12
+ padding: 0;
13
+ border: 0;
14
+ border-radius: var(--qr-radius);
15
+ background: var(--qr-paper);
16
+ cursor: pointer;
17
+
18
+ &:focus-visible {
19
+ @include focus-ring;
20
+ }
21
+ }
22
+
23
+ // Swapping the pair is the whole of the inverted state.
24
+ .root.inverted {
25
+ --qr-ink: var(--color-bg);
26
+ --qr-paper: var(--color-fg);
27
+ }
28
+
29
+ // The painted box. `relative` anchors the logo overlay — the one internal-anchor
30
+ // exception Rule 4 allows; it lives here rather than on `.root` so the overlay's
31
+ // percentage size resolves against the SYMBOL, not against the button.
32
+ .frame {
33
+ position: relative;
34
+ display: block;
35
+ max-width: 100%;
36
+ }
37
+
38
+ .svg {
39
+ display: block;
40
+ width: 100%;
41
+ height: auto;
42
+ border-radius: inherit;
43
+
44
+ // Forced-colors mode would override ink and paper with the same pair of
45
+ // system colours and flatten the symbol. For a QR code that is not "looks
46
+ // different", it is "does not scan" — the contrast IS the content.
47
+ forced-color-adjust: none;
48
+ }
49
+
50
+ .paper {
51
+ fill: var(--qr-paper);
52
+ }
53
+
54
+ .ink {
55
+ fill: var(--qr-ink);
56
+ }
57
+
58
+ // The mark is a CSS alpha mask filled with the current ink, so it recolours
59
+ // with the theme AND with the inverted state. `--qr-logo-src` / `--qr-logo-size`
60
+ // are set inline by the component.
61
+ .logo {
62
+ position: absolute;
63
+ top: 50%;
64
+ left: 50%;
65
+ width: var(--qr-logo-size, 0);
66
+ aspect-ratio: 1;
67
+ translate: -50% -50%;
68
+ background: var(--qr-ink);
69
+ mask-image: var(--qr-logo-src, none);
70
+ mask-repeat: no-repeat;
71
+ mask-position: center;
72
+ mask-size: contain;
73
+ }
74
+
75
+ // Compound selector so it wins over `.root` regardless of source order.
76
+ .root.error {
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ aspect-ratio: 1;
81
+ padding: var(--qr-error-padding);
82
+ background: var(--qr-error-bg);
83
+ color: var(--qr-error-fg);
84
+ font-size: var(--qr-error-font-size);
85
+ text-align: center;
86
+
87
+ // The plate's content is the consumer's name plus the message, and a name
88
+ // that is a URL or a bare ID is one unbreakable token — the default
89
+ // `overflow-wrap: normal` runs it straight out of the plate sideways.
90
+ // No `min-height` and no `overflow` here on purpose: `aspect-ratio` with an
91
+ // `auto` min-height already gives the box a content-based floor, so the
92
+ // square is a minimum and a wrapped name grows the plate instead of
93
+ // spilling. Pinning `min-height` to anything explicit REPLACES that
94
+ // automatic floor and reintroduces the vertical overflow.
95
+ overflow-wrap: anywhere;
96
+ cursor: default;
97
+ }
@@ -0,0 +1,17 @@
1
+ // QrCode.tokens.scss — Component-scoped tokens for <QrCode>. Ink and paper
2
+ // follow the theme; the `.inverted` class swaps the pair, which is why they are
3
+ // a pair of aliases rather than fixed values. Symbol geometry (the 4-module
4
+ // quiet zone, the punch side) is computed from the module count, not tokenised.
5
+ :root {
6
+ // The code itself. Swapped wholesale by `.inverted`.
7
+ --qr-ink: var(--color-fg);
8
+ --qr-paper: var(--color-bg);
9
+
10
+ --qr-radius: var(--radius-sm);
11
+
12
+ // Error plate — shown when the value is empty or too long to encode.
13
+ --qr-error-bg: var(--color-bg-muted);
14
+ --qr-error-fg: var(--color-fg);
15
+ --qr-error-font-size: var(--font-size-sm);
16
+ --qr-error-padding: var(--space-3);
17
+ }
@@ -0,0 +1,233 @@
1
+ import {
2
+ forwardRef,
3
+ useLayoutEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ type ButtonHTMLAttributes,
8
+ type CSSProperties,
9
+ type Ref,
10
+ } from 'react';
11
+ import clsx from 'clsx';
12
+ import { mergeRefs } from '../_internal/refs';
13
+ import { useTranslation } from '../../i18n';
14
+ import { cssUrl, encodeQr, snapWidth, type QrCodeLevel } from './qr';
15
+ import styles from './QrCode.module.scss';
16
+
17
+ export type { QrCodeLevel };
18
+
19
+ /** Share of the punch-out the mark fills, leaving paper around it. */
20
+ const LOGO_FILL = 0.72;
21
+
22
+ export interface QrCodeProps extends Omit<
23
+ ButtonHTMLAttributes<HTMLButtonElement>,
24
+ 'value' | 'type'
25
+ > {
26
+ /**
27
+ * The string to encode — a URL, an ID, a vCard. Encoded as UTF-8, so any
28
+ * script works.
29
+ *
30
+ * An empty string, or one past the largest symbol's capacity at the chosen
31
+ * `level` (~1273 bytes at `'H'`, ~2953 at `'L'`), renders a **disabled**
32
+ * button carrying a localized "unavailable" message instead of a code. It
33
+ * never throws — a long CRM field cannot white-screen a page.
34
+ */
35
+ value: string;
36
+ /**
37
+ * URL of a **single-colour** SVG to place in the centre. It is used as a CSS
38
+ * alpha mask and filled with the code's current ink, so it recolours itself
39
+ * in both themes and in the inverted state — the file's own colours are
40
+ * discarded. Full-colour artwork and photographs are not supported.
41
+ *
42
+ * Setting this also raises the default `level` to `'H'`, because the
43
+ * punch-out destroys modules outright.
44
+ */
45
+ logo?: string;
46
+ /**
47
+ * Error-correction level — how much damage the symbol survives. `'L'` ~7%,
48
+ * `'M'` ~15%, `'Q'` ~25%, `'H'` ~30%. Higher levels need a larger symbol for
49
+ * the same data. Defaults to `'H'` when `logo` is set, `'M'` otherwise.
50
+ */
51
+ level?: QrCodeLevel;
52
+ }
53
+
54
+ /**
55
+ * Snap the painted width down to a whole number of DEVICE pixels per module.
56
+ *
57
+ * A QR symbol only looks sharp when one module maps to an integer number of
58
+ * device pixels. It otherwise loses either way: `shape-rendering: crispEdges`
59
+ * snaps alternate modules to different widths (measured 4.878px/module
60
+ * rendering as a mix of 4px and 5px — a 20% jitter across the grid), while
61
+ * default antialiasing keeps the geometry even but spends most of a pixel
62
+ * blending every edge. Both read as a blurry code.
63
+ *
64
+ * So the component measures the box the parent gave it and paints the largest
65
+ * exact multiple that fits, centred, with the shortfall showing as a slightly
66
+ * wider quiet zone. The shortfall is up to ONE MODULE — `side / dpr` CSS px,
67
+ * not a fraction of a pixel — which is why `snapWidth` refuses the trade past
68
+ * a bounded share of the box.
69
+ *
70
+ * Returns `null` when it cannot measure (SSR, jsdom, a zero-width container,
71
+ * a box too small for even 1px per module) or when snapping would cost more
72
+ * than `snapWidth`'s budget; callers fall back to fluid `width: 100%` without
73
+ * `crispEdges`, which is the correct behaviour when the premise does not hold.
74
+ */
75
+ function useSnappedWidth(side: number): [Ref<HTMLButtonElement>, number | null] {
76
+ const hostRef = useRef<HTMLButtonElement | null>(null);
77
+ const [width, setWidth] = useState<number | null>(null);
78
+ // Tracked in state so a zoom change re-runs the effect and re-subscribes the
79
+ // media query below to the NEW ratio. Seeded from the real ratio rather than
80
+ // from 1: starting at 1 made the effect run twice on mount at any other dpr,
81
+ // and made the FIRST subscription `(resolution: 1dppx)` — a query that never
82
+ // matches on a 2dppx screen, so the initial zoom listener was dead.
83
+ const [dpr, setDpr] = useState(() => globalThis.devicePixelRatio || 1);
84
+
85
+ useLayoutEffect(() => {
86
+ const host = hostRef.current;
87
+ if (!host || side <= 0) return;
88
+
89
+ const recompute = () => {
90
+ const ratio = window.devicePixelRatio || 1;
91
+ setDpr(ratio);
92
+ // The arithmetic lives in `snapWidth` so it can be unit-tested directly,
93
+ // without a stubbed layout, across ratios jsdom cannot report.
94
+ setWidth(snapWidth(host.getBoundingClientRect().width, side, ratio));
95
+ };
96
+
97
+ recompute();
98
+
99
+ const cleanups: Array<() => void> = [];
100
+
101
+ if (typeof ResizeObserver !== 'undefined') {
102
+ const observer = new ResizeObserver(recompute);
103
+ observer.observe(host);
104
+ cleanups.push(() => observer.disconnect());
105
+ }
106
+
107
+ // Zooming changes devicePixelRatio WITHOUT changing our CSS width, so the
108
+ // ResizeObserver never fires for it. This does.
109
+ if (typeof window.matchMedia === 'function') {
110
+ const query = window.matchMedia(`(resolution: ${dpr}dppx)`);
111
+ query.addEventListener('change', recompute);
112
+ cleanups.push(() => query.removeEventListener('change', recompute));
113
+ }
114
+
115
+ return () => {
116
+ for (const cleanup of cleanups) cleanup();
117
+ };
118
+ }, [side, dpr]);
119
+
120
+ return [hostRef, width];
121
+ }
122
+
123
+ /**
124
+ * A scannable, theme-following QR code that fills its container; clicking swaps ink and paper.
125
+ * @see docs/components/QrCode.md
126
+ */
127
+ export const QrCode = forwardRef<HTMLButtonElement, QrCodeProps>(function QrCode(
128
+ { value, logo, level, className, style, onClick, title, 'aria-label': ariaLabel, ...props },
129
+ ref,
130
+ ) {
131
+ const t = useTranslation();
132
+ const [inverted, setInverted] = useState(false);
133
+
134
+ // One truthiness rule for the whole component: an empty string is not a logo,
135
+ // not a name and not a tooltip. Splitting this across `logo ?` and
136
+ // `logo !== undefined` punches a hole into a level-M symbol with nothing to
137
+ // fill it; the same slip on the name is below, at the `||` fallbacks.
138
+ const hasLogo = Boolean(logo);
139
+
140
+ const resolvedLevel: QrCodeLevel = level ?? (hasLogo ? 'H' : 'M');
141
+ const matrix = useMemo(() => encodeQr(value, resolvedLevel), [value, resolvedLevel]);
142
+
143
+ // Called unconditionally, before the error branch returns. `0` parks the hook
144
+ // when there is no symbol to measure for.
145
+ const [hostRef, snappedWidth] = useSnappedWidth(matrix?.side ?? 0);
146
+ // Memoized so the merged callback ref keeps its identity across renders —
147
+ // a fresh function would detach and reattach the node on every render.
148
+ const rootRef = useMemo(() => mergeRefs(ref, hostRef), [ref, hostRef]);
149
+
150
+ // {...props} first so the ARIA contract below cannot be clobbered — the
151
+ // component owns `type`, `aria-pressed` and the toggle. `aria-label` and
152
+ // `title` are destructured out instead, so the consumer's value is a
153
+ // FALLBACK rather than something the spread order silently eats.
154
+ if (matrix === null) {
155
+ return (
156
+ <button
157
+ {...props}
158
+ ref={rootRef}
159
+ type="button"
160
+ disabled
161
+ className={clsx(styles.root, styles.error, className)}
162
+ style={style}
163
+ title={title}
164
+ >
165
+ {/* The consumer's name goes in as CONTENT, not as a competing
166
+ aria-label: name-from-content then reads "<name> — <message>", so a
167
+ browse-mode user can tell WHICH code failed without hearing the
168
+ message twice. */}
169
+ {ariaLabel ? `${ariaLabel} — ${t('qrCode.error')}` : t('qrCode.error')}
170
+ </button>
171
+ );
172
+ }
173
+
174
+ const { side, path, punch } = matrix;
175
+ const offset = (side - punch) / 2;
176
+
177
+ const logoVars = logo
178
+ ? ({
179
+ '--qr-logo-src': cssUrl(logo),
180
+ '--qr-logo-size': `${((punch * LOGO_FILL) / side) * 100}%`,
181
+ } as CSSProperties)
182
+ : undefined;
183
+
184
+ return (
185
+ <button
186
+ {...props}
187
+ ref={rootRef}
188
+ type="button"
189
+ aria-pressed={inverted}
190
+ // `||`, not `??`, on both: `aria-label={row.name ?? ''}` is ordinary
191
+ // consumer code, and an empty aria-label does not remove the name — it
192
+ // drops the computation through to `title`, making the invert hint the
193
+ // name. `title=""` likewise means "no tooltip", not "empty tooltip".
194
+ aria-label={ariaLabel || t('qrCode.label')}
195
+ // `title` with an aria-label present is exposed as the DESCRIPTION, not
196
+ // the name — so it explains what pressing does without touching the
197
+ // name-exact contract. Doubles as a tooltip for sighted mouse users.
198
+ title={title || t('qrCode.invertHint')}
199
+ className={clsx(styles.root, inverted && styles.inverted, className)}
200
+ style={{ ...logoVars, ...style }}
201
+ onClick={(event) => {
202
+ setInverted((current) => !current);
203
+ onClick?.(event);
204
+ }}
205
+ >
206
+ {/* The painted box, up to one module narrower than the button so the
207
+ symbol lands on an exact module grid. It also anchors the logo
208
+ overlay, whose size is a percentage of the SYMBOL — not of the
209
+ button, which is why the anchor moved here. */}
210
+ <span className={styles.frame} style={{ width: snappedWidth ?? '100%' }}>
211
+ <svg
212
+ className={styles.svg}
213
+ viewBox={`0 0 ${side} ${side}`}
214
+ // `crispEdges` ONLY once the width is snapped. Unsnapped it is
215
+ // actively worse than antialiasing: it rounds each module's edges to
216
+ // the pixel grid independently, so adjacent modules come out
217
+ // different widths. Snapped, every module is the same whole number of
218
+ // device pixels and the symbol is pixel-exact.
219
+ shapeRendering={snappedWidth === null ? undefined : 'crispEdges'}
220
+ aria-hidden="true"
221
+ focusable="false"
222
+ >
223
+ <rect className={styles.paper} width={side} height={side} />
224
+ <path className={styles.ink} d={path} />
225
+ {hasLogo && (
226
+ <rect className={styles.paper} x={offset} y={offset} width={punch} height={punch} />
227
+ )}
228
+ </svg>
229
+ {hasLogo && <span className={styles.logo} aria-hidden="true" />}
230
+ </span>
231
+ </button>
232
+ );
233
+ });
@@ -0,0 +1,2 @@
1
+ export { QrCode } from './QrCode';
2
+ export type { QrCodeProps, QrCodeLevel } from './QrCode';
@@ -0,0 +1,161 @@
1
+ import qrcode from 'qrcode-generator';
2
+
3
+ /**
4
+ * Error-correction level — how much of the symbol can be destroyed and still
5
+ * decode. `'L'` ~7%, `'M'` ~15%, `'Q'` ~25%, `'H'` ~30%.
6
+ */
7
+ export type QrCodeLevel = 'L' | 'M' | 'Q' | 'H';
8
+
9
+ /** Quiet-zone width in modules. Four is the ISO/IEC 18004 minimum. */
10
+ const QUIET = 4;
11
+
12
+ /**
13
+ * The share of the symbol's WIDTH the centre punch-out occupies.
14
+ *
15
+ * Note the dimensions: level `'H'`'s ~30% recovery budget is a fraction of
16
+ * codewords, i.e. of AREA, so a width ratio is not directly comparable to it.
17
+ * After the odd-rounding below the realised width peaks at 28%, which is 7.8%
18
+ * of the area — nowhere near the limit. The real constraint on this number is
19
+ * visual, not arithmetic: bigger than about a quarter of the width and the
20
+ * mark stops reading as a mark in a code and starts reading as a hole punched
21
+ * through one.
22
+ */
23
+ const PUNCH_RATIO = 0.24;
24
+
25
+ /**
26
+ * UTF-8 bytes, re-expressed as a latin1 string.
27
+ *
28
+ * `qrcode-generator`'s default `stringToBytes` is `s.charCodeAt(i) & 0xff`,
29
+ * which silently truncates every code point above U+00FF — `'Привет'` encodes
30
+ * to garbage that still scans. Pre-encoding here turns that truncation into an
31
+ * identity function, because every char we hand it is already a single byte.
32
+ *
33
+ * The usual fix, assigning `qrcode.stringToBytes = …`, is shared mutable state
34
+ * on a module-level singleton: it would reach every other consumer of the
35
+ * package inside the host app. This stays local.
36
+ */
37
+ export function toByteString(value: string): string {
38
+ return Array.from(new TextEncoder().encode(value), (byte) => String.fromCharCode(byte)).join('');
39
+ }
40
+
41
+ /**
42
+ * Characters that would terminate a CSS `url("…")` early. Includes `\f`
43
+ * (U+000C FORM FEED): CSS input preprocessing (CSS Syntax Level 3 §3.3)
44
+ * converts every form feed to a line feed before tokenizing, so it is a
45
+ * newline for this purpose and closes the same breakout as `\n` and `\r`.
46
+ */
47
+ const CSS_URL_UNSAFE = /["'()\\\n\r\f]/g;
48
+
49
+ /**
50
+ * Wrap a consumer-supplied URL in a CSS `url("…")`, percent-encoding anything
51
+ * that could break out of the declaration. React does not sanitise custom
52
+ * properties, so this is a trust boundary.
53
+ *
54
+ * `encodeURI` is the wrong tool: it double-encodes `%` in already-encoded URLs
55
+ * and in `data:` URIs, which is most of what a logo is.
56
+ */
57
+ export function cssUrl(src: string): string {
58
+ const safe = src.replace(
59
+ CSS_URL_UNSAFE,
60
+ (char) => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`,
61
+ );
62
+ return `url("${safe}")`;
63
+ }
64
+
65
+ /** Geometry for one encoded symbol, in module units. */
66
+ export interface QrMatrix {
67
+ /** `viewBox` side — the module count plus both quiet zones. */
68
+ side: number;
69
+ /** A single SVG path covering every dark module, quiet-zone offset applied. */
70
+ path: string;
71
+ /** Side of the centred logo punch-out. Always odd, so it stays on module boundaries. */
72
+ punch: number;
73
+ }
74
+
75
+ /**
76
+ * Encode `value` and flatten it to SVG geometry. Returns `null` when there is
77
+ * nothing to encode (empty value) or the value exceeds the largest version at
78
+ * this level — both are the caller's error branch, never a throw.
79
+ */
80
+ export function encodeQr(value: string, level: QrCodeLevel): QrMatrix | null {
81
+ if (value === '') return null;
82
+
83
+ try {
84
+ const qr = qrcode(0, level); // 0 = pick the smallest version that fits
85
+ qr.addData(toByteString(value)); // always Byte mode; addData has no auto-detection
86
+ qr.make();
87
+
88
+ const count = qr.getModuleCount();
89
+ let path = '';
90
+ for (let row = 0; row < count; row += 1) {
91
+ for (let col = 0; col < count; col += 1) {
92
+ if (qr.isDark(row, col)) {
93
+ path += `M${col + QUIET} ${row + QUIET}h1v1h-1z`;
94
+ }
95
+ }
96
+ }
97
+
98
+ // `| 1` rounds up to the next odd number. The module count is always odd,
99
+ // so an odd punch keeps `(side - punch) / 2` integral. FLOOR, not ceil:
100
+ // double-rounding up puts a v1 symbol's punch at 33% of its width. Both
101
+ // variants sit inside level H's budget on area (7.8% flooring, ~11%
102
+ // ceiling, against ~30%) — flooring wins on looks, not on arithmetic. It
103
+ // caps the width at 28% for every version.
104
+ //
105
+ // Boundary the area maths does NOT cover: from version 7 up (59 bytes at
106
+ // level 'H', which is the default whenever `logo` is set) there is a centre
107
+ // alignment pattern, and the punch lands on it. Reed–Solomon protects data
108
+ // and ECC codewords, not function patterns, so no amount of budget buys
109
+ // that back. Decoders in practice extrapolate the module grid from the
110
+ // finder and timing patterns — which is why every commercial logo-QR
111
+ // generator gets away with it — but it is extrapolation, not recovery, and
112
+ // nothing here would notice it breaking. The playground demo carries an
113
+ // over-v7 logo example so the case is scannable by hand.
114
+ return { side: count + QUIET * 2, path, punch: Math.floor(count * PUNCH_RATIO) | 1 };
115
+ } catch {
116
+ return null;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * How much of the available width snapping may give up.
122
+ *
123
+ * Rounding down to a whole number of device pixels per module costs up to ONE
124
+ * MODULE — `side / dpr` CSS px, not a fraction of a pixel — and that is a
125
+ * share of the box, not a constant: at 41 modules and dpr 1 a 320px box loses
126
+ * 10%, a 200px box 18%, a 120px box 32%; a 177-module symbol in a 320px box
127
+ * loses 45%.
128
+ *
129
+ * A QR code exists to be scanned, and whether a camera resolves one depends on
130
+ * the ABSOLUTE size of a module, not on whether its edges are crisp. Unbounded
131
+ * snapping therefore shrinks the symbol hardest exactly where it is already
132
+ * tightest, and can push it under the ~100px floor the component's own docs
133
+ * warn about. An eighth is the line: past that, a bigger antialiased code
134
+ * beats a smaller pixel-exact one.
135
+ */
136
+ const MAX_SNAP_SHORTFALL = 1 / 8;
137
+
138
+ /**
139
+ * The largest painted width, in CSS pixels, that gives every module a whole
140
+ * number of DEVICE pixels — or `null` when that is impossible or too costly.
141
+ *
142
+ * A QR symbol only looks sharp at an integer scale. Off it, both rendering
143
+ * modes lose: `shape-rendering: crispEdges` rounds each module's edges to the
144
+ * pixel grid independently, so neighbours come out different widths (a measured
145
+ * 4.878px/module rendered as a mix of 4px and 5px), while default antialiasing
146
+ * keeps the geometry even but spends most of a pixel blending every edge.
147
+ *
148
+ * Returns `null` when there is nothing to measure (`available` of 0, as SSR and
149
+ * jsdom report), when the box cannot fit even one device pixel per module, or
150
+ * when the snap would cost more than `MAX_SNAP_SHORTFALL` of the width. In all
151
+ * three the caller should fall back to fluid width WITHOUT `crispEdges` —
152
+ * unsnapped, `crispEdges` is the worse of the two.
153
+ */
154
+ export function snapWidth(available: number, side: number, dpr: number): number | null {
155
+ if (!(available > 0) || !(side > 0) || !(dpr > 0)) return null;
156
+ const scale = Math.floor((available * dpr) / side);
157
+ if (scale < 1) return null;
158
+
159
+ const painted = (side * scale) / dpr;
160
+ return available - painted <= available * MAX_SNAP_SHORTFALL ? painted : null;
161
+ }