@sovereignfs/ui 0.83.1 → 0.89.1

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 (556) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/AppsLauncher.module.css +6 -0
  5. package/dist/Button.module.css +5 -0
  6. package/dist/Card.module.css +6 -0
  7. package/dist/CardTile.module.css +6 -0
  8. package/dist/CheckableListRow.module.css +8 -0
  9. package/dist/Checkbox.module.css +8 -0
  10. package/dist/CodeTextarea.module.css +6 -0
  11. package/dist/ColorPicker.module.css +6 -0
  12. package/dist/Combobox.module.css +6 -0
  13. package/dist/Command.module.css +6 -0
  14. package/dist/ConfirmDialog.module.css +6 -0
  15. package/dist/DatePicker.module.css +6 -0
  16. package/dist/Dialog.module.css +1 -1
  17. package/dist/DragHandleRow.module.css +6 -0
  18. package/dist/FileDropzone.module.css +25 -1
  19. package/dist/Header.module.css +6 -0
  20. package/dist/IconPicker.module.css +14 -4
  21. package/dist/Input.module.css +6 -0
  22. package/dist/LegalLinks.module.css +9 -2
  23. package/dist/Markdown.module.css +5 -0
  24. package/dist/Message.module.css +9 -0
  25. package/dist/MobileAppsDrawer.module.css +9 -5
  26. package/dist/MobileFooter.module.css +6 -0
  27. package/dist/NavList.module.css +11 -2
  28. package/dist/NavTabs.module.css +7 -1
  29. package/dist/NotificationsPanel.module.css +10 -0
  30. package/dist/QrCode.module.css +17 -0
  31. package/dist/QuantityStepper.module.css +4 -2
  32. package/dist/RadioGroup.module.css +6 -0
  33. package/dist/SegmentedControl.module.css +6 -0
  34. package/dist/Select.module.css +6 -0
  35. package/dist/Sheet.module.css +16 -1
  36. package/dist/SplitPane.module.css +1 -1
  37. package/dist/StepStrip.module.css +5 -3
  38. package/dist/SuggestionInput.module.css +12 -1
  39. package/dist/SwipableMobileCarouselDots.module.css +6 -0
  40. package/dist/SystemBanner.module.css +6 -0
  41. package/dist/Tabs.module.css +6 -0
  42. package/dist/TagInput.module.css +6 -0
  43. package/dist/Textarea.module.css +6 -0
  44. package/dist/Toast.module.css +5 -0
  45. package/dist/Toggle.module.css +7 -0
  46. package/dist/Tooltip.module.css +6 -0
  47. package/dist/UserMenu.module.css +5 -0
  48. package/dist/fonts/OFL.txt +93 -0
  49. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  50. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  51. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  52. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  53. package/dist/index.d.ts +121 -43
  54. package/dist/index.js +1410 -1152
  55. package/dist/tokens/fonts.css +53 -0
  56. package/dist/tokens/primitives.css +12 -12
  57. package/dist/tokens.css +2 -1
  58. package/package.json +24 -13
  59. package/src/__tests__/motion.test.tsx +0 -105
  60. package/src/__tests__/package-json.test.ts +0 -8
  61. package/src/components/Accordion/Accordion.module.css +0 -3
  62. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  63. package/src/components/Accordion/Accordion.tsx +0 -53
  64. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  65. package/src/components/Alert/Alert.module.css +0 -62
  66. package/src/components/Alert/Alert.stories.tsx +0 -96
  67. package/src/components/Alert/Alert.tsx +0 -58
  68. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  69. package/src/components/AppsLauncher/AppsLauncher.module.css +0 -96
  70. package/src/components/AppsLauncher/AppsLauncher.stories.tsx +0 -58
  71. package/src/components/AppsLauncher/AppsLauncher.tsx +0 -117
  72. package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +0 -52
  73. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  74. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  75. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  76. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  77. package/src/components/Avatar/Avatar.module.css +0 -38
  78. package/src/components/Avatar/Avatar.tsx +0 -42
  79. package/src/components/Badge/Badge.module.css +0 -177
  80. package/src/components/Badge/Badge.stories.tsx +0 -238
  81. package/src/components/Badge/Badge.tsx +0 -84
  82. package/src/components/Badge/__tests__/Badge.test.tsx +0 -90
  83. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  84. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  85. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  86. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  87. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  88. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  89. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  90. package/src/components/Button/Button.module.css +0 -169
  91. package/src/components/Button/Button.stories.tsx +0 -83
  92. package/src/components/Button/Button.tsx +0 -52
  93. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  94. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  95. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  96. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  97. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  98. package/src/components/Calendar/Calendar.module.css +0 -126
  99. package/src/components/Calendar/Calendar.tsx +0 -213
  100. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  101. package/src/components/Calendar/dateUtils.ts +0 -97
  102. package/src/components/Card/Card.module.css +0 -42
  103. package/src/components/Card/Card.tsx +0 -34
  104. package/src/components/CardTile/CardTile.module.css +0 -181
  105. package/src/components/CardTile/CardTile.stories.tsx +0 -86
  106. package/src/components/CardTile/CardTile.tsx +0 -128
  107. package/src/components/CardTile/__tests__/CardTile.test.tsx +0 -56
  108. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  109. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  110. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  111. package/src/components/Checkbox/Checkbox.module.css +0 -111
  112. package/src/components/Checkbox/Checkbox.tsx +0 -78
  113. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  114. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  115. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  116. package/src/components/Collapsible/Collapsible.module.css +0 -70
  117. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  118. package/src/components/Collapsible/Collapsible.tsx +0 -66
  119. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  120. package/src/components/ColorPicker/ColorPicker.module.css +0 -132
  121. package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -80
  122. package/src/components/ColorPicker/ColorPicker.tsx +0 -157
  123. package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +0 -117
  124. package/src/components/Combobox/Combobox.module.css +0 -122
  125. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  126. package/src/components/Combobox/Combobox.tsx +0 -186
  127. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  128. package/src/components/Command/Command.module.css +0 -80
  129. package/src/components/Command/Command.stories.tsx +0 -104
  130. package/src/components/Command/Command.tsx +0 -168
  131. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  132. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  133. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -150
  134. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -214
  135. package/src/components/ConsentPrompt/ConsentPrompt.module.css +0 -21
  136. package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +0 -31
  137. package/src/components/ConsentPrompt/ConsentPrompt.tsx +0 -66
  138. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  139. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  140. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  141. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  142. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  143. package/src/components/DataTable/DataTable.module.css +0 -28
  144. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  145. package/src/components/DataTable/DataTable.tsx +0 -154
  146. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  147. package/src/components/DatePicker/DatePicker.module.css +0 -61
  148. package/src/components/DatePicker/DatePicker.tsx +0 -103
  149. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  150. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  151. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  152. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  153. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  154. package/src/components/Dialog/Dialog.module.css +0 -335
  155. package/src/components/Dialog/Dialog.stories.tsx +0 -324
  156. package/src/components/Dialog/Dialog.tsx +0 -254
  157. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -318
  158. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  159. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -42
  160. package/src/components/Drawer/Drawer.module.css +0 -121
  161. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  162. package/src/components/Drawer/Drawer.tsx +0 -175
  163. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -226
  164. package/src/components/EmptyState/EmptyState.module.css +0 -27
  165. package/src/components/EmptyState/EmptyState.tsx +0 -27
  166. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  167. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  168. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  169. package/src/components/FormField/FormField.module.css +0 -33
  170. package/src/components/FormField/FormField.tsx +0 -78
  171. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  172. package/src/components/GripIcon/GripIcon.tsx +0 -27
  173. package/src/components/Header/Header.module.css +0 -62
  174. package/src/components/Header/Header.stories.tsx +0 -452
  175. package/src/components/Header/Header.tsx +0 -102
  176. package/src/components/Header/__tests__/Header.test.tsx +0 -104
  177. package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +0 -21
  178. package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +0 -111
  179. package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +0 -54
  180. package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +0 -58
  181. package/src/components/HoverCard/HoverCard.module.css +0 -3
  182. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  183. package/src/components/HoverCard/HoverCard.tsx +0 -111
  184. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  185. package/src/components/Icon/Icon.module.css +0 -27
  186. package/src/components/Icon/Icon.stories.tsx +0 -95
  187. package/src/components/Icon/Icon.tsx +0 -43
  188. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  189. package/src/components/Icon/icons/activity.tsx +0 -20
  190. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  191. package/src/components/Icon/icons/apple.tsx +0 -21
  192. package/src/components/Icon/icons/arrow-left-right.tsx +0 -23
  193. package/src/components/Icon/icons/banana.tsx +0 -21
  194. package/src/components/Icon/icons/beef.tsx +0 -22
  195. package/src/components/Icon/icons/beer.tsx +0 -24
  196. package/src/components/Icon/icons/bell.tsx +0 -21
  197. package/src/components/Icon/icons/bold.tsx +0 -20
  198. package/src/components/Icon/icons/calendar.tsx +0 -23
  199. package/src/components/Icon/icons/candy.tsx +0 -24
  200. package/src/components/Icon/icons/carrot.tsx +0 -22
  201. package/src/components/Icon/icons/check.tsx +0 -20
  202. package/src/components/Icon/icons/chevron-down.tsx +0 -20
  203. package/src/components/Icon/icons/chevron-left.tsx +0 -20
  204. package/src/components/Icon/icons/chevron-right.tsx +0 -20
  205. package/src/components/Icon/icons/chevron-up.tsx +0 -20
  206. package/src/components/Icon/icons/circle-check.tsx +0 -21
  207. package/src/components/Icon/icons/circle-chevron-left.tsx +0 -21
  208. package/src/components/Icon/icons/circle-x.tsx +0 -22
  209. package/src/components/Icon/icons/code.tsx +0 -21
  210. package/src/components/Icon/icons/coffee.tsx +0 -23
  211. package/src/components/Icon/icons/cookie.tsx +0 -25
  212. package/src/components/Icon/icons/copy.tsx +0 -21
  213. package/src/components/Icon/icons/credit-card.tsx +0 -21
  214. package/src/components/Icon/icons/croissant.tsx +0 -24
  215. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  216. package/src/components/Icon/icons/database.tsx +0 -22
  217. package/src/components/Icon/icons/download.tsx +0 -22
  218. package/src/components/Icon/icons/drumstick.tsx +0 -21
  219. package/src/components/Icon/icons/egg.tsx +0 -20
  220. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  221. package/src/components/Icon/icons/external-link.tsx +0 -22
  222. package/src/components/Icon/icons/eye-off.tsx +0 -23
  223. package/src/components/Icon/icons/eye.tsx +0 -21
  224. package/src/components/Icon/icons/file-text.tsx +0 -24
  225. package/src/components/Icon/icons/file.tsx +0 -21
  226. package/src/components/Icon/icons/fish.tsx +0 -25
  227. package/src/components/Icon/icons/folder-closed.tsx +0 -21
  228. package/src/components/Icon/icons/folder-open.tsx +0 -20
  229. package/src/components/Icon/icons/folder.tsx +0 -20
  230. package/src/components/Icon/icons/folders.tsx +0 -21
  231. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  232. package/src/components/Icon/icons/hat-glasses.tsx +0 -24
  233. package/src/components/Icon/icons/history.tsx +0 -22
  234. package/src/components/Icon/icons/house.tsx +0 -21
  235. package/src/components/Icon/icons/inbox.tsx +0 -21
  236. package/src/components/Icon/icons/index.ts +0 -394
  237. package/src/components/Icon/icons/info.tsx +0 -22
  238. package/src/components/Icon/icons/italic.tsx +0 -22
  239. package/src/components/Icon/icons/layers.tsx +0 -22
  240. package/src/components/Icon/icons/layout-dashboard.tsx +0 -23
  241. package/src/components/Icon/icons/layout-grid.tsx +0 -23
  242. package/src/components/Icon/icons/link.tsx +0 -21
  243. package/src/components/Icon/icons/list-ordered.tsx +0 -25
  244. package/src/components/Icon/icons/list.tsx +0 -25
  245. package/src/components/Icon/icons/lock.tsx +0 -21
  246. package/src/components/Icon/icons/log-out.tsx +0 -22
  247. package/src/components/Icon/icons/luggage.tsx +0 -24
  248. package/src/components/Icon/icons/mail.tsx +0 -21
  249. package/src/components/Icon/icons/map-pin.tsx +0 -21
  250. package/src/components/Icon/icons/menu.tsx +0 -22
  251. package/src/components/Icon/icons/milk.tsx +0 -22
  252. package/src/components/Icon/icons/minus.tsx +0 -20
  253. package/src/components/Icon/icons/package.tsx +0 -23
  254. package/src/components/Icon/icons/paint-bucket.tsx +0 -23
  255. package/src/components/Icon/icons/panel-left.tsx +0 -21
  256. package/src/components/Icon/icons/pencil.tsx +0 -21
  257. package/src/components/Icon/icons/pin.tsx +0 -21
  258. package/src/components/Icon/icons/pizza.tsx +0 -24
  259. package/src/components/Icon/icons/plus.tsx +0 -21
  260. package/src/components/Icon/icons/rectangle-ellipsis.tsx +0 -23
  261. package/src/components/Icon/icons/refresh-cw.tsx +0 -23
  262. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  263. package/src/components/Icon/icons/rotate-cw.tsx +0 -21
  264. package/src/components/Icon/icons/route.tsx +0 -22
  265. package/src/components/Icon/icons/salad.tsx +0 -24
  266. package/src/components/Icon/icons/search.tsx +0 -21
  267. package/src/components/Icon/icons/send.tsx +0 -21
  268. package/src/components/Icon/icons/settings.tsx +0 -21
  269. package/src/components/Icon/icons/share-2.tsx +0 -24
  270. package/src/components/Icon/icons/sheet.tsx +0 -24
  271. package/src/components/Icon/icons/shield.tsx +0 -20
  272. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  273. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  274. package/src/components/Icon/icons/smartphone.tsx +0 -21
  275. package/src/components/Icon/icons/snowflake.tsx +0 -31
  276. package/src/components/Icon/icons/spray-can.tsx +0 -29
  277. package/src/components/Icon/icons/square-kanban.tsx +0 -23
  278. package/src/components/Icon/icons/table.tsx +0 -23
  279. package/src/components/Icon/icons/trash-2.tsx +0 -24
  280. package/src/components/Icon/icons/upload.tsx +0 -22
  281. package/src/components/Icon/icons/user-round-plus.tsx +0 -23
  282. package/src/components/Icon/icons/user.tsx +0 -21
  283. package/src/components/Icon/icons/users.tsx +0 -23
  284. package/src/components/Icon/icons/wine.tsx +0 -23
  285. package/src/components/Icon/icons/x.tsx +0 -21
  286. package/src/components/IconPicker/IconPicker.module.css +0 -63
  287. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  288. package/src/components/IconPicker/IconPicker.tsx +0 -90
  289. package/src/components/Input/Input.module.css +0 -52
  290. package/src/components/Input/Input.stories.tsx +0 -86
  291. package/src/components/Input/Input.tsx +0 -20
  292. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  293. package/src/components/Item/Item.module.css +0 -70
  294. package/src/components/Item/Item.stories.tsx +0 -62
  295. package/src/components/Item/Item.tsx +0 -54
  296. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  297. package/src/components/Kbd/Kbd.module.css +0 -14
  298. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  299. package/src/components/Kbd/Kbd.tsx +0 -12
  300. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  301. package/src/components/Label/Label.module.css +0 -11
  302. package/src/components/Label/Label.stories.tsx +0 -40
  303. package/src/components/Label/Label.tsx +0 -24
  304. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  305. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  306. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  307. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  308. package/src/components/Markdown/Markdown.module.css +0 -73
  309. package/src/components/Markdown/Markdown.stories.tsx +0 -40
  310. package/src/components/Markdown/Markdown.tsx +0 -305
  311. package/src/components/Markdown/__tests__/Markdown.test.tsx +0 -144
  312. package/src/components/Marker/Marker.module.css +0 -33
  313. package/src/components/Marker/Marker.stories.tsx +0 -39
  314. package/src/components/Marker/Marker.tsx +0 -34
  315. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  316. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  317. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  318. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  319. package/src/components/Menu/Menu.module.css +0 -90
  320. package/src/components/Menu/Menu.tsx +0 -209
  321. package/src/components/Menu/__tests__/Menu.test.tsx +0 -227
  322. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  323. package/src/components/Menubar/Menubar.tsx +0 -42
  324. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  325. package/src/components/Message/Message.module.css +0 -99
  326. package/src/components/Message/Message.stories.tsx +0 -79
  327. package/src/components/Message/Message.tsx +0 -41
  328. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  329. package/src/components/MessageScroller/MessageScroller.module.css +0 -65
  330. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  331. package/src/components/MessageScroller/MessageScroller.tsx +0 -84
  332. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  333. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -82
  334. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  335. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  336. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  337. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  338. package/src/components/MobileFooter/MobileFooter.tsx +0 -122
  339. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -129
  340. package/src/components/MobileHeader/MobileHeader.module.css +0 -76
  341. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  342. package/src/components/MobileHeader/MobileHeader.tsx +0 -90
  343. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -113
  344. package/src/components/NavList/NavList.module.css +0 -130
  345. package/src/components/NavList/NavList.tsx +0 -136
  346. package/src/components/NavList/__tests__/NavList.test.tsx +0 -109
  347. package/src/components/NavTabs/NavTabs.module.css +0 -50
  348. package/src/components/NavTabs/NavTabs.tsx +0 -61
  349. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  350. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  351. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  352. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  353. package/src/components/NotificationsPanel/NotificationsPanel.module.css +0 -258
  354. package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +0 -61
  355. package/src/components/NotificationsPanel/NotificationsPanel.tsx +0 -187
  356. package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +0 -78
  357. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  358. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  359. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  360. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -77
  361. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -69
  362. package/src/components/PageContainer/PageContainer.module.css +0 -82
  363. package/src/components/PageContainer/PageContainer.tsx +0 -64
  364. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -70
  365. package/src/components/PageHeader/PageHeader.module.css +0 -86
  366. package/src/components/PageHeader/PageHeader.tsx +0 -176
  367. package/src/components/PageHeader/__tests__/PageHeader.test.tsx +0 -103
  368. package/src/components/PageLayout/PageLayout.module.css +0 -51
  369. package/src/components/PageLayout/PageLayout.stories.tsx +0 -73
  370. package/src/components/PageLayout/PageLayout.tsx +0 -51
  371. package/src/components/PageLayout/__tests__/PageLayout.test.tsx +0 -34
  372. package/src/components/Pagination/Pagination.module.css +0 -98
  373. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  374. package/src/components/Pagination/Pagination.tsx +0 -87
  375. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  376. package/src/components/Popover/Popover.module.css +0 -74
  377. package/src/components/Popover/Popover.stories.tsx +0 -357
  378. package/src/components/Popover/Popover.tsx +0 -290
  379. package/src/components/Popover/__tests__/Popover.test.tsx +0 -263
  380. package/src/components/Progress/Progress.module.css +0 -20
  381. package/src/components/Progress/Progress.stories.tsx +0 -40
  382. package/src/components/Progress/Progress.tsx +0 -35
  383. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  384. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  385. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  386. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  387. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  388. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  389. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  390. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  391. package/src/components/Resizable/Resizable.module.css +0 -70
  392. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  393. package/src/components/Resizable/Resizable.tsx +0 -313
  394. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  395. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  396. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  397. package/src/components/RootLayout/RootLayout.module.css +0 -12
  398. package/src/components/RootLayout/RootLayout.stories.tsx +0 -125
  399. package/src/components/RootLayout/RootLayout.tsx +0 -185
  400. package/src/components/RootLayout/__tests__/RootLayout.test.tsx +0 -161
  401. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  402. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  403. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  404. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  405. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  406. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  407. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  408. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  409. package/src/components/Select/Select.module.css +0 -82
  410. package/src/components/Select/Select.stories.tsx +0 -115
  411. package/src/components/Select/Select.tsx +0 -48
  412. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  413. package/src/components/Sheet/Sheet.module.css +0 -58
  414. package/src/components/Sheet/Sheet.tsx +0 -109
  415. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  416. package/src/components/Slider/Slider.module.css +0 -95
  417. package/src/components/Slider/Slider.stories.tsx +0 -64
  418. package/src/components/Slider/Slider.tsx +0 -77
  419. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  420. package/src/components/Spinner/Spinner.module.css +0 -39
  421. package/src/components/Spinner/Spinner.tsx +0 -23
  422. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  423. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  424. package/src/components/SplitPane/SplitPane.module.css +0 -85
  425. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  426. package/src/components/SplitPane/SplitPane.tsx +0 -149
  427. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  428. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  429. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  430. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  431. package/src/components/StepStrip/StepStrip.module.css +0 -53
  432. package/src/components/StepStrip/StepStrip.tsx +0 -74
  433. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  434. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  435. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  436. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -64
  437. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -243
  438. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  439. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  440. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  441. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  442. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  443. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -214
  444. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  445. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  446. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -64
  447. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -73
  448. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  449. package/src/components/SwipeStack/SwipeStack.module.css +0 -101
  450. package/src/components/SwipeStack/SwipeStack.tsx +0 -199
  451. package/src/components/SwipeStack/SwipeStackCard.tsx +0 -22
  452. package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +0 -169
  453. package/src/components/SystemBanner/SystemBanner.module.css +0 -79
  454. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  455. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  456. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  457. package/src/components/Table/Table.module.css +0 -45
  458. package/src/components/Table/Table.stories.tsx +0 -125
  459. package/src/components/Table/Table.tsx +0 -51
  460. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  461. package/src/components/Tabs/Tabs.module.css +0 -56
  462. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  463. package/src/components/Tabs/Tabs.tsx +0 -46
  464. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  465. package/src/components/TagInput/TagInput.module.css +0 -141
  466. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  467. package/src/components/TagInput/TagInput.tsx +0 -174
  468. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  469. package/src/components/Textarea/Textarea.module.css +0 -47
  470. package/src/components/Textarea/Textarea.tsx +0 -38
  471. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -51
  472. package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +0 -35
  473. package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +0 -152
  474. package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +0 -87
  475. package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +0 -78
  476. package/src/components/Toast/Toast.module.css +0 -191
  477. package/src/components/Toast/Toast.stories.tsx +0 -191
  478. package/src/components/Toast/Toast.tsx +0 -139
  479. package/src/components/Toggle/Toggle.module.css +0 -57
  480. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  481. package/src/components/Toggle/Toggle.tsx +0 -39
  482. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  483. package/src/components/Tooltip/Tooltip.module.css +0 -56
  484. package/src/components/Tooltip/Tooltip.tsx +0 -30
  485. package/src/components/Typography/Typography.module.css +0 -47
  486. package/src/components/Typography/Typography.stories.tsx +0 -62
  487. package/src/components/Typography/Typography.tsx +0 -30
  488. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  489. package/src/components/UserMenu/UserMenu.module.css +0 -90
  490. package/src/components/UserMenu/UserMenu.stories.tsx +0 -49
  491. package/src/components/UserMenu/UserMenu.tsx +0 -132
  492. package/src/components/UserMenu/__tests__/UserMenu.test.tsx +0 -77
  493. package/src/css-modules.d.ts +0 -4
  494. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  495. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  496. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  497. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  498. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  499. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  500. package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +0 -118
  501. package/src/hooks/__tests__/useReorderSensors.test.ts +0 -26
  502. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  503. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -175
  504. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  505. package/src/hooks/__tests__/useSwipeStack.test.tsx +0 -155
  506. package/src/hooks/index.ts +0 -33
  507. package/src/hooks/useCarouselRouteSync.ts +0 -92
  508. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  509. package/src/hooks/useDoubleTap.ts +0 -91
  510. package/src/hooks/useIsMobile.ts +0 -33
  511. package/src/hooks/useIsOffline.ts +0 -41
  512. package/src/hooks/useLongPress.ts +0 -185
  513. package/src/hooks/useOfflineTileState.ts +0 -45
  514. package/src/hooks/usePublishShellChromeHeight.ts +0 -96
  515. package/src/hooks/useReorderSensors.ts +0 -88
  516. package/src/hooks/useResponsiveLayout.ts +0 -36
  517. package/src/hooks/useSnapCarousel.ts +0 -284
  518. package/src/hooks/useSwipeReveal.ts +0 -107
  519. package/src/hooks/useSwipeStack.ts +0 -235
  520. package/src/index.ts +0 -311
  521. package/src/motion.ts +0 -78
  522. package/src/overlay-shell.ts +0 -159
  523. package/src/scroll-lock.ts +0 -22
  524. package/src/stories/Avatar.stories.tsx +0 -44
  525. package/src/stories/Card.stories.tsx +0 -35
  526. package/src/stories/Checkbox.stories.tsx +0 -45
  527. package/src/stories/DesignSystemOverview.stories.tsx +0 -3793
  528. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  529. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  530. package/src/stories/DragHandleRow.stories.tsx +0 -41
  531. package/src/stories/EmptyState.stories.tsx +0 -33
  532. package/src/stories/FileDropzone.stories.tsx +0 -69
  533. package/src/stories/FormField.stories.tsx +0 -47
  534. package/src/stories/GripIcon.stories.tsx +0 -29
  535. package/src/stories/InteractionHooks.stories.tsx +0 -925
  536. package/src/stories/LayoutSystem.stories.tsx +0 -639
  537. package/src/stories/MenuEntries.stories.tsx +0 -86
  538. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  539. package/src/stories/NavList.stories.tsx +0 -147
  540. package/src/stories/NavTabs.stories.tsx +0 -53
  541. package/src/stories/OfflineGate.stories.tsx +0 -42
  542. package/src/stories/PageContainer.stories.tsx +0 -82
  543. package/src/stories/PageHeader.stories.tsx +0 -95
  544. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  545. package/src/stories/Spinner.stories.tsx +0 -25
  546. package/src/stories/StepStrip.stories.tsx +0 -76
  547. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -362
  548. package/src/stories/SwipeStack.stories.tsx +0 -200
  549. package/src/stories/Textarea.stories.tsx +0 -63
  550. package/src/stories/TokenGallery.stories.tsx +0 -652
  551. package/src/stories/Tooltip.stories.tsx +0 -59
  552. package/src/tokens/primitives.css +0 -168
  553. package/src/tokens/semantic.css +0 -162
  554. package/src/tokens/theme-presets.css +0 -33
  555. package/src/tokens/theme-presets.ts +0 -72
  556. package/src/tokens.css +0 -5
@@ -1,305 +0,0 @@
1
- import { Fragment, type ReactNode } from 'react';
2
- import { Typography } from '../Typography/Typography';
3
- import styles from './Markdown.module.css';
4
-
5
- export interface MarkdownProps {
6
- /** Raw markdown source. Supports: headings (#/##/###), paragraphs,
7
- * **bold**, *italic*, `code`, [links](url), unordered lists (-), ordered
8
- * lists (1. / 1)), fenced code blocks (```), and blockquotes (>),
9
- * including soft-wrapped continuation lines within a paragraph or list
10
- * item. Not a general-purpose CommonMark parser — no tables, images, or
11
- * nested blocks. */
12
- content: string;
13
- /** Renders every line within a paragraph on its own visual line (a
14
- * `<br>` between them) instead of the default CommonMark-style soft-wrap
15
- * (consecutive lines joined with a single space, requiring a blank line
16
- * for a new paragraph). Off by default — the soft-wrap behavior is
17
- * correct for this component's primary use (long-form, first-party
18
- * content authored *as* markdown, where a hard line break is a
19
- * deliberate `\` ` or blank-line choice). Turn this on when rendering
20
- * plain, user-typed multi-line text that happens to be passed through
21
- * this component (e.g. a card description or comment body edited in an
22
- * ordinary `<textarea>`) — there, every Enter press is a real,
23
- * intentional line break the user typed, and silently collapsing it
24
- * into one run-on paragraph reads as broken, not as "markdown
25
- * formatting applied." */
26
- preserveLineBreaks?: boolean;
27
- className?: string;
28
- }
29
-
30
- let inlineKey = 0;
31
-
32
- /** Schemes allowed in a rendered `[text](url)` link's `href`. Anything else —
33
- * most importantly `javascript:` — is rejected: `content` here can be
34
- * LLM-generated (Warden's chat replies), so a prompt-injected document or a
35
- * compromised model is a realistic way for an attacker-chosen URL to end up
36
- * in this position. */
37
- const SAFE_HREF_SCHEMES = new Set(['http', 'https', 'mailto', 'tel']);
38
-
39
- function isSafeHref(href: string): boolean {
40
- const scheme = /^([a-zA-Z][a-zA-Z\d+.-]*):/.exec(href)?.[1];
41
- return scheme === undefined || SAFE_HREF_SCHEMES.has(scheme.toLowerCase());
42
- }
43
-
44
- /** Returns a link's `href` value ready to render, or `null` to reject it.
45
- * Rejecting is what keeps an unsafe URL out of the DOM; `encodeURI` on top
46
- * is the contextual output-encoding this class of finding calls for. The
47
- * sink below reads this function's *return value*, never the raw `href` —
48
- * a boolean guard around the original string still leaves the tainted
49
- * value itself flowing into `href`. Browsers ignore tabs/newlines when
50
- * parsing a URL's scheme, so those are stripped first to close a
51
- * `jav\tascript:`-style bypass; `encodeURI` throws on a lone unpaired
52
- * surrogate, hence the try/catch. */
53
- function sanitizeHref(href: string): string | null {
54
- const normalized = href.replace(/[\t\n\r]/g, '').trim();
55
- if (!normalized || !isSafeHref(normalized)) return null;
56
- try {
57
- return encodeURI(normalized);
58
- } catch {
59
- return null;
60
- }
61
- }
62
-
63
- /** Parses **bold**, *italic*, `code`, and [text](url) within a line of text. */
64
- function parseInline(text: string): ReactNode[] {
65
- const nodes: ReactNode[] = [];
66
- const pattern = /\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|\*([^*]+)\*|`([^`]+)`/;
67
- let remaining = text;
68
-
69
- while (remaining.length > 0) {
70
- const match = pattern.exec(remaining);
71
- if (!match) {
72
- nodes.push(remaining);
73
- break;
74
- }
75
- if (match.index > 0) nodes.push(remaining.slice(0, match.index));
76
-
77
- const [full, linkText, linkHref, boldText, italicText, codeText] = match;
78
- const key = `md-inline-${inlineKey++}`;
79
- if (linkHref !== undefined) {
80
- const safeHref = sanitizeHref(linkHref);
81
- nodes.push(
82
- safeHref !== null ? (
83
- <a key={key} href={safeHref}>
84
- {linkText}
85
- </a>
86
- ) : (
87
- linkText
88
- ),
89
- );
90
- } else if (boldText !== undefined) {
91
- nodes.push(<strong key={key}>{boldText}</strong>);
92
- } else if (italicText !== undefined) {
93
- nodes.push(<em key={key}>{italicText}</em>);
94
- } else if (codeText !== undefined) {
95
- nodes.push(<code key={key}>{codeText}</code>);
96
- }
97
- remaining = remaining.slice(match.index + full.length);
98
- }
99
-
100
- return nodes;
101
- }
102
-
103
- const isQuote = (l: string) => l.startsWith('> ') || l === '>';
104
- const isListItem = (l: string) => l.startsWith('- ');
105
- const isHeading = (l: string) => /^#{1,3}\s+/.test(l);
106
- /** ```` ```lang ```` — an opening (or closing) code fence. */
107
- const isFence = (l: string) => /^\s*`{3,}/.test(l);
108
- /** `1. item` or `1) item`. Bounded digit count so a long numeric line
109
- * can't be mistaken for a list marker. */
110
- const isOrderedItem = (l: string) => /^\d{1,9}[.)]\s+/.test(l);
111
- /** A line that ends the current *paragraph* run — a blank line, or the
112
- * start of a heading, quote, list, or code block. Anything else (including
113
- * an indented continuation line) is folded into the paragraph, matching how
114
- * the source markdown soft-wraps prose across lines. */
115
- const endsParagraph = (l: string) =>
116
- l.trim() === '' || isHeading(l) || isQuote(l) || isListItem(l) || isOrderedItem(l) || isFence(l);
117
- /** A line that ends the current *unordered list* run — a blank line, or the
118
- * start of a heading, quote, code block, or an *ordered* item. Deliberately
119
- * does NOT include `isListItem`: a list item's own opening line legitimately
120
- * satisfies `isListItem`, so reusing `endsParagraph` here (which does) would
121
- * treat the first line of every list as ending the list before it started —
122
- * the list-collection loop would then never advance, looping forever. */
123
- const endsList = (l: string) =>
124
- l.trim() === '' || isHeading(l) || isQuote(l) || isFence(l) || isOrderedItem(l);
125
- /** The ordered-list mirror of `endsList` — excludes `isOrderedItem` for the
126
- * same reason, and treats an unordered item as the start of a new block. */
127
- const endsOrderedList = (l: string) =>
128
- l.trim() === '' || isHeading(l) || isQuote(l) || isFence(l) || isListItem(l);
129
-
130
- function parseBlocks(content: string, preserveLineBreaks: boolean): ReactNode[] {
131
- const lines = content.replace(/\r\n/g, '\n').split('\n');
132
- const blocks: ReactNode[] = [];
133
- let i = 0;
134
- let blockKey = 0;
135
-
136
- while (i < lines.length) {
137
- const line = lines[i] ?? '';
138
-
139
- if (line.trim() === '') {
140
- i++;
141
- continue;
142
- }
143
-
144
- // Checked before every other block type: everything between the fences
145
- // is verbatim, including blank lines and lines that would otherwise
146
- // read as headings, quotes, or list items.
147
- if (isFence(line)) {
148
- const fenceMatch = /^\s*(`{3,})(.*)$/.exec(line);
149
- const fence = fenceMatch?.[1] ?? '```';
150
- const language = (fenceMatch?.[2] ?? '').trim();
151
- const closing = new RegExp(`^\\s*${fence}\\s*$`);
152
- i++;
153
- const codeLines: string[] = [];
154
- while (i < lines.length && !closing.test(lines[i] ?? '')) {
155
- codeLines.push(lines[i] ?? '');
156
- i++;
157
- }
158
- // Steps past the closing fence; a no-op at end of input, so an
159
- // unterminated fence renders the remainder as code (as CommonMark
160
- // does) rather than looping.
161
- i++;
162
- blocks.push(
163
- <div key={blockKey++} className={styles.block}>
164
- <pre className={styles.codeBlock}>
165
- <code data-language={language || undefined}>{codeLines.join('\n')}</code>
166
- </pre>
167
- </div>,
168
- );
169
- continue;
170
- }
171
-
172
- const heading = /^(#{1,3})\s+(.*)$/.exec(line);
173
- if (heading) {
174
- const level = (heading[1]?.length ?? 1) as 1 | 2 | 3;
175
- blocks.push(
176
- <div key={blockKey++} className={styles.block} data-heading>
177
- <Typography variant={`h${level}` as 'h1' | 'h2' | 'h3'}>
178
- {parseInline(heading[2] ?? '')}
179
- </Typography>
180
- </div>,
181
- );
182
- i++;
183
- continue;
184
- }
185
-
186
- if (isQuote(line)) {
187
- const quoteLines: string[] = [];
188
- while (i < lines.length && isQuote(lines[i] ?? '')) {
189
- quoteLines.push((lines[i] ?? '').slice(2));
190
- i++;
191
- }
192
- blocks.push(
193
- <div key={blockKey++} className={styles.block}>
194
- <blockquote className={styles.blockquote}>
195
- <Typography variant="body" as="p">
196
- {parseInline(quoteLines.join(' '))}
197
- </Typography>
198
- </blockquote>
199
- </div>,
200
- );
201
- continue;
202
- }
203
-
204
- if (isOrderedItem(line)) {
205
- const items: string[] = [];
206
- let start: number | undefined;
207
- while (i < lines.length && !endsOrderedList(lines[i] ?? '')) {
208
- const current = lines[i] ?? '';
209
- const match = /^(\d{1,9})[.)]\s+(.*)$/.exec(current);
210
- if (match) {
211
- // Honour the author's own starting number (a list resuming at 4),
212
- // but let the browser number the rest — markdown's own numbers
213
- // are conventionally ignored after the first.
214
- if (start === undefined) start = Number(match[1]);
215
- items.push(match[2] ?? '');
216
- } else {
217
- const lastIndex = items.length - 1;
218
- items[lastIndex] = `${items[lastIndex] ?? ''} ${current.trim()}`;
219
- }
220
- i++;
221
- }
222
- blocks.push(
223
- <div key={blockKey++} className={styles.block}>
224
- <ol
225
- className={styles.list}
226
- start={start !== undefined && start !== 1 ? start : undefined}
227
- >
228
- {items.map((item, idx) => (
229
- <Typography key={idx} variant="body" as="li">
230
- {parseInline(item)}
231
- </Typography>
232
- ))}
233
- </ol>
234
- </div>,
235
- );
236
- continue;
237
- }
238
-
239
- if (isListItem(line)) {
240
- const items: string[] = [];
241
- while (i < lines.length && !endsList(lines[i] ?? '')) {
242
- const current = lines[i] ?? '';
243
- if (isListItem(current)) {
244
- items.push(current.slice(2));
245
- } else {
246
- // Continuation of the previous item's wrapped text.
247
- const lastIndex = items.length - 1;
248
- items[lastIndex] = `${items[lastIndex] ?? ''} ${current.trim()}`;
249
- }
250
- i++;
251
- }
252
- blocks.push(
253
- <div key={blockKey++} className={styles.block}>
254
- <ul className={styles.list}>
255
- {items.map((item, idx) => (
256
- <Typography key={idx} variant="body" as="li">
257
- {parseInline(item)}
258
- </Typography>
259
- ))}
260
- </ul>
261
- </div>,
262
- );
263
- continue;
264
- }
265
-
266
- const paraLines: string[] = [];
267
- while (i < lines.length && !endsParagraph(lines[i] ?? '')) {
268
- paraLines.push((lines[i] ?? '').trim());
269
- i++;
270
- }
271
- blocks.push(
272
- <div key={blockKey++} className={styles.block}>
273
- <Typography variant="body" as="p">
274
- {preserveLineBreaks
275
- ? paraLines.map((paraLine, lineIdx) => (
276
- <Fragment key={lineIdx}>
277
- {lineIdx > 0 && <br />}
278
- {parseInline(paraLine)}
279
- </Fragment>
280
- ))
281
- : parseInline(paraLines.join(' '))}
282
- </Typography>
283
- </div>,
284
- );
285
- }
286
-
287
- return blocks;
288
- }
289
-
290
- /** Renders a constrained markdown subset (see MarkdownProps) as styled React
291
- * elements built from Typography — no HTML string injection. Primarily
292
- * meant for long-form, first-party content pages (privacy policy, terms of
293
- * service) sourced from a single markdown file — not a general-purpose
294
- * CommonMark renderer for arbitrary markdown. Also fine for plain,
295
- * user-typed multi-line text (a card description, a comment body) edited
296
- * in an ordinary `<textarea>` and passed through unchanged, as long as
297
- * `preserveLineBreaks` is set — see that prop's own doc comment for why it
298
- * isn't the default. */
299
- export function Markdown({ content, preserveLineBreaks = false, className }: MarkdownProps) {
300
- return (
301
- <div className={[styles.root, className].filter(Boolean).join(' ')}>
302
- {parseBlocks(content, preserveLineBreaks)}
303
- </div>
304
- );
305
- }
@@ -1,144 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import { cleanup, render } from '@testing-library/react';
4
- import { Markdown } from '../Markdown';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('Markdown', () => {
9
- it('joins consecutive lines into one paragraph by default (soft-wrap)', () => {
10
- const { container } = render(<Markdown content={'Line one.\nLine two.'} />);
11
- const p = container.querySelector('p');
12
- expect(p?.textContent).toBe('Line one. Line two.');
13
- expect(p?.querySelector('br')).toBeNull();
14
- });
15
-
16
- it('preserveLineBreaks keeps each line on its own line via <br>', () => {
17
- const { container } = render(
18
- <Markdown content={'Line one.\nLine two.\nLine three.'} preserveLineBreaks />,
19
- );
20
- const p = container.querySelector('p');
21
- expect(p?.querySelectorAll('br')).toHaveLength(2);
22
- expect(p?.textContent).toBe('Line one.Line two.Line three.');
23
- });
24
-
25
- it('preserveLineBreaks still starts a new paragraph on a blank line', () => {
26
- const { container } = render(
27
- <Markdown content={'First paragraph.\n\nSecond paragraph.'} preserveLineBreaks />,
28
- );
29
- const paragraphs = container.querySelectorAll('p');
30
- expect(paragraphs).toHaveLength(2);
31
- expect(paragraphs[0]?.textContent).toBe('First paragraph.');
32
- expect(paragraphs[1]?.textContent).toBe('Second paragraph.');
33
- });
34
-
35
- it('preserveLineBreaks does not affect headings, quotes, or lists', () => {
36
- const { container } = render(
37
- <Markdown content={'# Heading\n\n- item one\n- item two'} preserveLineBreaks />,
38
- );
39
- expect(container.querySelector('h1')?.textContent).toBe('Heading');
40
- expect(container.querySelectorAll('li')).toHaveLength(2);
41
- });
42
- });
43
-
44
- describe('Markdown — ordered lists and fenced code', () => {
45
- it('renders an ordered list, numbering from the browser', () => {
46
- const { container } = render(<Markdown content={'1. first\n2. second\n3. third'} />);
47
-
48
- const list = container.querySelector('ol');
49
- expect(list).not.toBeNull();
50
- expect([...(list?.querySelectorAll('li') ?? [])].map((li) => li.textContent)).toEqual([
51
- 'first',
52
- 'second',
53
- 'third',
54
- ]);
55
- expect(list?.getAttribute('start')).toBeNull();
56
- });
57
-
58
- it('honours a list that starts at a number other than 1', () => {
59
- const { container } = render(<Markdown content={'4. fourth\n5. fifth'} />);
60
- expect(container.querySelector('ol')?.getAttribute('start')).toBe('4');
61
- });
62
-
63
- it('accepts the 1) marker style and applies inline formatting inside items', () => {
64
- const { container } = render(<Markdown content={'1) do **this**'} />);
65
-
66
- expect(container.querySelector('ol')).not.toBeNull();
67
- expect(container.querySelector('ol strong')?.textContent).toBe('this');
68
- });
69
-
70
- it('keeps ordered and unordered lists as separate blocks', () => {
71
- const { container } = render(<Markdown content={'- bullet\n1. number'} />);
72
-
73
- expect(container.querySelectorAll('ul')).toHaveLength(1);
74
- expect(container.querySelectorAll('ol')).toHaveLength(1);
75
- });
76
-
77
- it('renders a fenced code block verbatim, without parsing its contents', () => {
78
- const content = ['```ts', 'const a = 1; // **not bold**', '', '# not a heading', '```'].join(
79
- '\n',
80
- );
81
- const { container } = render(<Markdown content={content} />);
82
-
83
- const code = container.querySelector('pre code');
84
- expect(code?.textContent).toBe('const a = 1; // **not bold**\n\n# not a heading');
85
- expect(container.querySelector('strong')).toBeNull();
86
- expect(container.querySelector('h1')).toBeNull();
87
- });
88
-
89
- it('exposes the fence language for styling hooks', () => {
90
- const { container } = render(<Markdown content={'```python\nx = 1\n```'} />);
91
- expect(container.querySelector('pre code')?.getAttribute('data-language')).toBe('python');
92
- });
93
-
94
- it('terminates on an unclosed fence instead of looping', () => {
95
- const { container } = render(<Markdown content={'text\n\n```\nnever closed'} />);
96
- expect(container.querySelector('pre code')?.textContent).toBe('never closed');
97
- });
98
-
99
- it('separates a code block from the paragraph before it', () => {
100
- const { container } = render(<Markdown content={'Try this:\n```\nrun me\n```'} />);
101
-
102
- expect(container.querySelector('p')?.textContent).toBe('Try this:');
103
- expect(container.querySelector('pre code')?.textContent).toBe('run me');
104
- });
105
- });
106
-
107
- describe('Markdown — link hrefs', () => {
108
- it('renders an http(s) link as a real anchor', () => {
109
- const { container } = render(<Markdown content={'[docs](https://example.com/docs)'} />);
110
- const link = container.querySelector('a');
111
- expect(link?.getAttribute('href')).toBe('https://example.com/docs');
112
- expect(link?.textContent).toBe('docs');
113
- });
114
-
115
- it('renders a relative link as a real anchor', () => {
116
- const { container } = render(<Markdown content={'[here](/warden/models)'} />);
117
- expect(container.querySelector('a')?.getAttribute('href')).toBe('/warden/models');
118
- });
119
-
120
- it('renders a mailto: link as a real anchor', () => {
121
- const { container } = render(<Markdown content={'[email](mailto:a@example.com)'} />);
122
- expect(container.querySelector('a')?.getAttribute('href')).toBe('mailto:a@example.com');
123
- });
124
-
125
- it('neutralizes a javascript: URL instead of making it clickable', () => {
126
- const { container } = render(
127
- <Markdown content={'[click me](javascript:alert(document.cookie))'} />,
128
- );
129
- expect(container.querySelector('a')).toBeNull();
130
- expect(container.textContent).toContain('click me');
131
- });
132
-
133
- it('neutralizes a javascript: URL disguised with an embedded tab', () => {
134
- const { container } = render(<Markdown content={'[x](jav\tascript:alert(1))'} />);
135
- expect(container.querySelector('a')).toBeNull();
136
- });
137
-
138
- it('neutralizes a data: URL', () => {
139
- const { container } = render(
140
- <Markdown content={'[x](data:text/html,<script>alert(1)</script>)'} />,
141
- );
142
- expect(container.querySelector('a')).toBeNull();
143
- });
144
- });
@@ -1,33 +0,0 @@
1
- .marker {
2
- display: inline-flex;
3
- align-items: center;
4
- justify-content: center;
5
- min-width: 16px;
6
- height: 16px;
7
- padding: 0 4px;
8
- margin: 0 1px;
9
- border: none;
10
- border-radius: var(--sv-radius-full);
11
- background: var(--sv-color-accent-subtle);
12
- color: var(--sv-color-accent);
13
- font-family: var(--sv-font-family);
14
- font-size: var(--sv-font-size-label);
15
- font-weight: var(--sv-font-weight-semibold);
16
- line-height: 1;
17
- vertical-align: super;
18
- }
19
-
20
- button.marker {
21
- cursor: pointer;
22
- }
23
-
24
- button.marker:focus-visible {
25
- outline: 2px solid var(--sv-color-focus-ring);
26
- outline-offset: 1px;
27
- }
28
-
29
- @media (hover: hover) {
30
- button.marker:hover {
31
- background: color-mix(in srgb, var(--sv-color-accent-subtle) 70%, var(--sv-color-accent) 30%);
32
- }
33
- }
@@ -1,39 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Marker } from './Marker';
3
-
4
- const meta = {
5
- title: 'Components/Marker',
6
- component: Marker,
7
- parameters: {
8
- layout: 'padded',
9
- docs: {
10
- description: {
11
- component:
12
- 'Inline citation/reference marker, for attributing part of an assistant answer to a source (Sovereign Harness "source trace").',
13
- },
14
- },
15
- },
16
- args: { index: 1, label: 'Source: Notes' },
17
- } satisfies Meta<typeof Marker>;
18
-
19
- export default meta;
20
- type Story = StoryObj<typeof meta>;
21
-
22
- // ---------------------------------------------------------------------------
23
-
24
- export const Static: Story = {};
25
-
26
- export const Clickable: Story = {
27
- args: { onClick: () => {} },
28
- };
29
-
30
- export const InContext: Story = {
31
- render: () => (
32
- <p style={{ fontSize: 14, maxWidth: 400 }}>
33
- Your next task deadline is Thursday
34
- <Marker index={1} label="Source: Tasks" onClick={() => {}} />, and you have two unread
35
- messages from the team
36
- <Marker index={2} label="Source: Notes" onClick={() => {}} />.
37
- </p>
38
- ),
39
- };
@@ -1,34 +0,0 @@
1
- import styles from './Marker.module.css';
2
-
3
- export interface MarkerProps {
4
- /** The number shown in the marker, e.g. 1, 2, 3. */
5
- index: number;
6
- /** Accessible label describing the citation, e.g. "Source: Notes". */
7
- label: string;
8
- /** Reveals source details (e.g. opens a source trace panel) when given. */
9
- onClick?: () => void;
10
- className?: string;
11
- }
12
-
13
- /**
14
- * Marker — inline citation/reference marker, for attributing part of an
15
- * assistant's answer to a source (matches RFC 0040's "source trace" —
16
- * Harness shows which plugin/data source informed an answer).
17
- */
18
- export function Marker({ index, label, onClick, className }: MarkerProps) {
19
- const classes = [styles.marker, className].filter(Boolean).join(' ');
20
-
21
- if (onClick) {
22
- return (
23
- <button type="button" onClick={onClick} aria-label={label} className={classes}>
24
- {index}
25
- </button>
26
- );
27
- }
28
-
29
- return (
30
- <span aria-label={label} className={classes}>
31
- {index}
32
- </span>
33
- );
34
- }
@@ -1,23 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, render, screen } from '@testing-library/react';
4
- import { Marker } from '../Marker';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('Marker', () => {
9
- it('renders as a static span with an accessible label when no onClick is given', () => {
10
- render(<Marker index={1} label="Source: Notes" />);
11
- const el = screen.getByLabelText('Source: Notes');
12
- expect(el.tagName).toBe('SPAN');
13
- expect(el.textContent).toBe('1');
14
- });
15
-
16
- it('renders as a button and fires onClick when given', () => {
17
- const onClick = vi.fn();
18
- render(<Marker index={2} label="Source: Tasks" onClick={onClick} />);
19
- const el = screen.getByRole('button', { name: 'Source: Tasks' });
20
- el.click();
21
- expect(onClick).toHaveBeenCalled();
22
- });
23
- });
@@ -1,27 +0,0 @@
1
- .group {
2
- display: grid;
3
- gap: var(--sv-space-2);
4
- }
5
-
6
- .label {
7
- font-size: var(--sv-font-size-xs);
8
- font-weight: var(--sv-font-weight-semibold);
9
- color: var(--sv-color-text-muted);
10
- }
11
-
12
- .row {
13
- display: flex;
14
- align-items: center;
15
- justify-content: space-between;
16
- gap: var(--sv-space-2);
17
- }
18
-
19
- .trailing {
20
- flex-shrink: 0;
21
- max-width: 8rem;
22
- }
23
-
24
- .hint {
25
- font-size: var(--sv-font-size-xs);
26
- color: var(--sv-color-text-muted);
27
- }
@@ -1,74 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { CurrencyInput } from '../CurrencyInput/CurrencyInput';
4
- import { MemberMultiSelect, type MemberMultiSelectOption } from './MemberMultiSelect';
5
-
6
- const meta = {
7
- title: 'Components/MemberMultiSelect',
8
- component: MemberMultiSelect,
9
- parameters: {
10
- layout: 'padded',
11
- docs: {
12
- description: {
13
- component:
14
- 'Checkbox list for picking any number of people from an already-resolved set of options. Domain-agnostic about who an option represents — instance users and guest members are both just `{id, label}`, so nothing special is needed to include guests. Not a directory search or invite flow; pair with SuggestionInput for that.',
15
- },
16
- },
17
- },
18
- args: {
19
- options: [],
20
- selectedIds: new Set(),
21
- onToggle: () => {},
22
- },
23
- } satisfies Meta<typeof MemberMultiSelect>;
24
-
25
- export default meta;
26
- type Story = StoryObj<typeof meta>;
27
-
28
- const OPTIONS: MemberMultiSelectOption[] = [
29
- { id: '1', label: 'Priya' },
30
- { id: '2', label: 'Jamie (guest)' },
31
- { id: '3', label: 'Sam' },
32
- ];
33
-
34
- function ControlledMultiSelect({ withTrailing = false }: { withTrailing?: boolean }) {
35
- const [selected, setSelected] = useState<Set<string>>(new Set(['1', '3']));
36
- const [amounts, setAmounts] = useState<Record<string, number | null>>({});
37
-
38
- return (
39
- <MemberMultiSelect
40
- options={OPTIONS}
41
- selectedIds={selected}
42
- onToggle={(id, checked) => {
43
- setSelected((prev) => {
44
- const next = new Set(prev);
45
- if (checked) next.add(id);
46
- else next.delete(id);
47
- return next;
48
- });
49
- }}
50
- label="Split between"
51
- hint={withTrailing ? 'Remaining: 0.00' : undefined}
52
- renderTrailing={
53
- withTrailing
54
- ? (id) => (
55
- <CurrencyInput
56
- valueCents={amounts[id] ?? null}
57
- onValueChange={(cents) => setAmounts((prev) => ({ ...prev, [id]: cents }))}
58
- placeholder="0.00"
59
- aria-label={`Amount for ${OPTIONS.find((o) => o.id === id)?.label}`}
60
- />
61
- )
62
- : undefined
63
- }
64
- />
65
- );
66
- }
67
-
68
- export const Default: Story = {
69
- render: () => <ControlledMultiSelect />,
70
- };
71
-
72
- export const WithTrailingAmountInput: Story = {
73
- render: () => <ControlledMultiSelect withTrailing />,
74
- };