@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,58 +0,0 @@
1
- 'use client';
2
-
3
- import type { ReactNode } from 'react';
4
- import { EmptyState } from '../EmptyState/EmptyState';
5
-
6
- export interface DeviceOnlyGateProps {
7
- children: ReactNode;
8
- /** Defaults to a generic "this app" phrasing — pass the plugin's own name. */
9
- surfaceName?: string;
10
- /**
11
- * The caller's own `isDeviceOnlyTierAvailable()` result (from
12
- * `@sovereignfs/sdk/device-client`) — taken as a plain boolean rather than
13
- * computed inside this component, so `@sovereignfs/ui` never depends on
14
- * `@sovereignfs/sdk` (this package must stay usable standalone, outside the
15
- * plugin runtime — RFC 0073).
16
- */
17
- available: boolean;
18
- className?: string;
19
- }
20
-
21
- /**
22
- * DeviceOnlyGate — blocks a `device-only`-tier plugin's content from
23
- * rendering on a surface that cannot provide the durable, encrypted,
24
- * device-auth-gated store that tier requires, showing an explanatory empty
25
- * state instead of a broken screen (research 0012, epic tasks 2.33 + 3.36).
26
- *
27
- * A `device-only` plugin wraps its own root content in this the same way
28
- * Console and Account wrap theirs in `OfflineGate` — an opt-in pattern each
29
- * surface applies to itself, not a platform-level route gate. The launcher
30
- * tile's own "Phone only" badge (`useOfflineTileState`) is advisory UI on top
31
- * of this; this component is the actual gate, since a user can always reach a
32
- * route directly (a bookmark, a deep link) without passing through the
33
- * launcher tile at all.
34
- *
35
- * **Not a security boundary.** Availability here is a capability signal, not
36
- * an authorization check — the real protection for `device-only` data is
37
- * that it is encrypted and the key requires device auth to release (epic task
38
- * 1.22), so it stays inaccessible regardless of whether this gate is present,
39
- * bypassed, or simply never reached (e.g. a hand-crafted request against the
40
- * plugin's own API routes).
41
- */
42
- export function DeviceOnlyGate({
43
- children,
44
- surfaceName,
45
- available,
46
- className,
47
- }: DeviceOnlyGateProps) {
48
- if (available) return <>{children}</>;
49
-
50
- return (
51
- <EmptyState
52
- icon="smartphone"
53
- heading="Phone only"
54
- description={`${surfaceName ?? 'This app'} is only available on a phone with secure storage set up.`}
55
- className={className}
56
- />
57
- );
58
- }
@@ -1,45 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import { cleanup, render, screen } from '@testing-library/react';
4
- import { DeviceOnlyGate } from '../DeviceOnlyGate';
5
-
6
- describe('DeviceOnlyGate', () => {
7
- afterEach(cleanup);
8
-
9
- it('renders children unchanged when available', () => {
10
- render(
11
- <DeviceOnlyGate available={true}>
12
- <p>Wallet content</p>
13
- </DeviceOnlyGate>,
14
- );
15
- expect(screen.getByText('Wallet content')).toBeDefined();
16
- });
17
-
18
- it('replaces children with an explanatory empty state when unavailable', () => {
19
- render(
20
- <DeviceOnlyGate available={false}>
21
- <p>Wallet content</p>
22
- </DeviceOnlyGate>,
23
- );
24
- expect(screen.queryByText('Wallet content')).toBeNull();
25
- expect(screen.getByText('Phone only')).toBeDefined();
26
- });
27
-
28
- it('names the surface in the message when provided', () => {
29
- render(
30
- <DeviceOnlyGate available={false} surfaceName="Wallet">
31
- <p>Wallet content</p>
32
- </DeviceOnlyGate>,
33
- );
34
- expect(screen.getByText(/Wallet is only available on a phone/)).toBeDefined();
35
- });
36
-
37
- it('falls back to generic phrasing with no surface name', () => {
38
- render(
39
- <DeviceOnlyGate available={false}>
40
- <p>Wallet content</p>
41
- </DeviceOnlyGate>,
42
- );
43
- expect(screen.getByText(/This app is only available on a phone/)).toBeDefined();
44
- });
45
- });
@@ -1,100 +0,0 @@
1
- 'use client';
2
-
3
- import type { ReactNode } from 'react';
4
- import { EmptyState } from '../EmptyState/EmptyState';
5
-
6
- /**
7
- * `'checking'` covers the moment before the caller's own async status check
8
- * resolves — same transitional-state pattern `EncryptionSection`'s local
9
- * `LocalState` uses, so this gate never flashes an empty state before the
10
- * real answer is known. `'no-device-auth'` is the hard-block case (RFC 0093
11
- * §5, epic task 1.22): the environment supports the tier, but this device
12
- * has no passcode, fingerprint, or face unlock configured, so a key cannot
13
- * be created here at all — distinct from `'not-set-up'`, where it can.
14
- */
15
- export type DeviceStorageKeyGateStatus =
16
- 'checking' | 'unsupported' | 'no-device-auth' | 'not-set-up' | 'set-up';
17
-
18
- export interface DeviceStorageKeyGateProps {
19
- children: ReactNode;
20
- /** Defaults to a generic "This app" phrasing — pass the plugin's own name. */
21
- surfaceName?: string;
22
- /**
23
- * The caller's own `getDeviceStorageKeyStatus()` result (from
24
- * `@sovereignfs/sdk/device-only-storage`) — taken as a plain status rather
25
- * than computed inside this component, so `@sovereignfs/ui` never depends
26
- * on `@sovereignfs/sdk` (same boundary `DeviceOnlyGate`'s `available` prop
27
- * draws — this package must stay usable standalone, outside the plugin
28
- * runtime — RFC 0073).
29
- */
30
- status: DeviceStorageKeyGateStatus;
31
- /**
32
- * Rendered under the "not set up" message — typically a link to Account →
33
- * Security. Not built in here: this package depends on no router, so the
34
- * caller supplies its own navigable element (a plain `<a>`, a framework
35
- * `<Link>`, whatever the host app uses).
36
- */
37
- setupAction?: ReactNode;
38
- className?: string;
39
- }
40
-
41
- /**
42
- * DeviceStorageKeyGate — blocks a `device-only`-tier plugin's content until
43
- * the user has set up their Device Storage Key (RFC 0093 §2, epic task
44
- * 1.22). Distinct from `DeviceOnlyGate`: that one checks whether the *tier
45
- * itself* is available on this surface (native shell, secure-storage bridge
46
- * present); this one checks whether the user has actually completed the
47
- * one-time, per-device enrollment that tier depends on. A `device-only`
48
- * plugin typically wants both — `DeviceOnlyGate` outermost (no point
49
- * checking enrollment on a surface that cannot offer the tier at all), this
50
- * gate inside it.
51
- *
52
- * Enrollment is centralized and decoupled from any single plugin (RFC 0093
53
- * §2): a plugin that finds no key set up does not run its own enrollment
54
- * ceremony inline. It stops here and points the user at Account → Security —
55
- * the one place enrollment happens for every `device-only` plugin on this
56
- * device — via `setupAction`, the same opt-in, self-applied pattern
57
- * `OfflineGate`/`DeviceOnlyGate` already use for their own surfaces.
58
- */
59
- export function DeviceStorageKeyGate({
60
- children,
61
- surfaceName,
62
- status,
63
- setupAction,
64
- className,
65
- }: DeviceStorageKeyGateProps) {
66
- if (status === 'checking') return null;
67
- if (status === 'set-up') return <>{children}</>;
68
-
69
- if (status === 'unsupported') {
70
- return (
71
- <EmptyState
72
- icon="smartphone"
73
- heading="Phone only"
74
- description={`${surfaceName ?? 'This app'} needs a security feature (WebAuthn PRF and Origin Private File System support) that isn't available here.`}
75
- className={className}
76
- />
77
- );
78
- }
79
-
80
- if (status === 'no-device-auth') {
81
- return (
82
- <EmptyState
83
- icon="alert-triangle"
84
- heading="Set up a device passcode"
85
- description={`${surfaceName ?? 'This app'} needs a passcode, fingerprint, or face unlock set up on this device before its Device Storage Key can be created. Set one up in your device's system settings, then come back.`}
86
- className={className}
87
- />
88
- );
89
- }
90
-
91
- return (
92
- <EmptyState
93
- icon="lock"
94
- heading="Set up your Device Storage Key"
95
- description={`${surfaceName ?? 'This app'} keeps its data only on this device, protected by a Device Storage Key you set up once in Account → Security.`}
96
- action={setupAction}
97
- className={className}
98
- />
99
- );
100
- }
@@ -1,119 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import { cleanup, render, screen } from '@testing-library/react';
4
- import { DeviceStorageKeyGate } from '../DeviceStorageKeyGate';
5
-
6
- describe('DeviceStorageKeyGate', () => {
7
- afterEach(cleanup);
8
-
9
- it('renders nothing while checking', () => {
10
- const { container } = render(
11
- <DeviceStorageKeyGate status="checking">
12
- <p>Notes content</p>
13
- </DeviceStorageKeyGate>,
14
- );
15
- expect(container.firstChild).toBeNull();
16
- });
17
-
18
- it('renders children unchanged once set up', () => {
19
- render(
20
- <DeviceStorageKeyGate status="set-up">
21
- <p>Notes content</p>
22
- </DeviceStorageKeyGate>,
23
- );
24
- expect(screen.getByText('Notes content')).toBeDefined();
25
- });
26
-
27
- it('shows a "Phone only"-style message when the environment is unsupported', () => {
28
- render(
29
- <DeviceStorageKeyGate status="unsupported">
30
- <p>Notes content</p>
31
- </DeviceStorageKeyGate>,
32
- );
33
- expect(screen.queryByText('Notes content')).toBeNull();
34
- expect(screen.getByText('Phone only')).toBeDefined();
35
- });
36
-
37
- it('shows the setup message and prompt when not-set-up', () => {
38
- render(
39
- <DeviceStorageKeyGate status="not-set-up">
40
- <p>Notes content</p>
41
- </DeviceStorageKeyGate>,
42
- );
43
- expect(screen.queryByText('Notes content')).toBeNull();
44
- expect(screen.getByText('Set up your Device Storage Key')).toBeDefined();
45
- });
46
-
47
- it('names the surface in the not-set-up message when provided', () => {
48
- render(
49
- <DeviceStorageKeyGate status="not-set-up" surfaceName="Notes">
50
- <p>Notes content</p>
51
- </DeviceStorageKeyGate>,
52
- );
53
- expect(screen.getByText(/Notes keeps its data only on this device/)).toBeDefined();
54
- });
55
-
56
- it('falls back to generic phrasing with no surface name', () => {
57
- render(
58
- <DeviceStorageKeyGate status="not-set-up">
59
- <p>Notes content</p>
60
- </DeviceStorageKeyGate>,
61
- );
62
- expect(screen.getByText(/This app keeps its data only on this device/)).toBeDefined();
63
- });
64
-
65
- it('renders the caller-supplied setupAction when not-set-up', () => {
66
- render(
67
- <DeviceStorageKeyGate
68
- status="not-set-up"
69
- setupAction={<a href="/account/security">Go to Account → Security</a>}
70
- >
71
- <p>Notes content</p>
72
- </DeviceStorageKeyGate>,
73
- );
74
- expect(screen.getByRole('link', { name: 'Go to Account → Security' })).toBeDefined();
75
- });
76
-
77
- it('renders no setupAction when unsupported, even if one is passed', () => {
78
- render(
79
- <DeviceStorageKeyGate
80
- status="unsupported"
81
- setupAction={<a href="/account/security">Go to Account → Security</a>}
82
- >
83
- <p>Notes content</p>
84
- </DeviceStorageKeyGate>,
85
- );
86
- expect(screen.queryByRole('link')).toBeNull();
87
- });
88
-
89
- it('shows the hard-block message when no-device-auth', () => {
90
- render(
91
- <DeviceStorageKeyGate status="no-device-auth">
92
- <p>Notes content</p>
93
- </DeviceStorageKeyGate>,
94
- );
95
- expect(screen.queryByText('Notes content')).toBeNull();
96
- expect(screen.getByText('Set up a device passcode')).toBeDefined();
97
- });
98
-
99
- it('names the surface in the no-device-auth message when provided', () => {
100
- render(
101
- <DeviceStorageKeyGate status="no-device-auth" surfaceName="Notes">
102
- <p>Notes content</p>
103
- </DeviceStorageKeyGate>,
104
- );
105
- expect(screen.getByText(/Notes needs a passcode, fingerprint, or face unlock/)).toBeDefined();
106
- });
107
-
108
- it('renders no setupAction when no-device-auth, even if one is passed — fixing this is a device settings change, not a Sovereign link', () => {
109
- render(
110
- <DeviceStorageKeyGate
111
- status="no-device-auth"
112
- setupAction={<a href="/account/security">Go to Account → Security</a>}
113
- >
114
- <p>Notes content</p>
115
- </DeviceStorageKeyGate>,
116
- );
117
- expect(screen.queryByRole('link')).toBeNull();
118
- });
119
- });
@@ -1,335 +0,0 @@
1
- /* Dialog — scrim + centered panel. Tokens only (z-index is structural, not a
2
- * theming value, so it has no token).
3
- *
4
- * `sm`/`md` are a fixed WIDTH but a content-driven height, capped at a
5
- * per-size max-height: the panel grows to fit its content and shrinks when
6
- * content is sparse, only hitting the cap (and scrolling internally, inside
7
- * `.content`) once content actually exceeds it. Before this, height was
8
- * fixed too, which left short-content consumers (e.g. a two-field form in
9
- * console/plugins/PluginAccessDialog.tsx) looking like a near-empty
10
- * skeleton — see docs/architecture-rules.md. `auto` goes further — content-
11
- * driven on BOTH width and height, each independently capped rather than
12
- * either being fixed — for content whose natural footprint varies enough
13
- * (a card detail modal with an optional checklist/comments section) that a
14
- * single fixed width doesn't fit it well either short or long. `lg` is a
15
- * true fixed box (100%/100% of the scrim's available area) — no current
16
- * overlay-shell plugin renders into it (Console did until workstream 0022
17
- * moved it to `shell: "default"`; Account never resized off `overlaySize:
18
- * "lg"`'s original default until epic task 14.5, see `fixed` below).
19
- * `fixed` (named after its own behavior, not after this file's always-
20
- * applied `.panel` wrapper class below) is also a true fixed box, width
21
- * AND height both set — same "content never resizes it" guarantee as `lg`
22
- * — but capped rather than filling the viewport, for a plugin whose
23
- * settings-panel-shaped content doesn't warrant `lg`'s full-screen footprint
24
- * (Account's own case, epic task 14.5 round 3). The close button stays
25
- * pinned top-right regardless. The scrim's padding is the fixed margin
26
- * `lg`/`fixed` leave around the viewport; `sm`/`md`/`auto` are centered and
27
- * cap to that available space on short screens too. On mobile every size
28
- * becomes a full-screen sheet.
29
- *
30
- * `--sv-dialog-inset-left` lets a host inset the scrim past a fixed left nav
31
- * rail (e.g. the platform sidebar) so the overlay's left margin is measured
32
- * from the rail, not the viewport edge, and the rail stays visible/usable.
33
- * `--sv-dialog-inset-top` (RFC 0013) mirrors this on the vertical axis: the
34
- * shell sets it to the mobile header height so the header stays visible and
35
- * interactive above the dialog sheet. Defaults to 0 for standalone use. */
36
-
37
- .scrim {
38
- position: fixed;
39
- top: var(--sv-dialog-inset-top, 0);
40
- right: 0;
41
- bottom: 0;
42
- left: 0;
43
- z-index: 100;
44
- display: flex;
45
- align-items: center;
46
- justify-content: center;
47
- /* left edge always 0 so the backdrop covers the full viewport incl. sidebar.
48
- padding-left offsets the panel's available area to start at the rail edge. */
49
- padding: var(--sv-space-8);
50
- padding-left: calc(var(--sv-dialog-inset-left, 0px) + var(--sv-space-8));
51
- background: var(--sv-color-scrim);
52
- /* Entrance/exit fade. The Dialog component drives this via a two-phase
53
- mount (see motion.ts) — .scrimOpen is added one frame after mount so this
54
- transition has somewhere to animate from, and removed (while staying
55
- mounted) for the exit before the component actually unmounts. */
56
- opacity: 0;
57
- transition: opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out);
58
- }
59
-
60
- .scrimOpen {
61
- opacity: 1;
62
- }
63
-
64
- .panel {
65
- position: relative;
66
- display: flex;
67
- flex-direction: column;
68
- overflow: hidden;
69
- background: var(--sv-color-surface-raised);
70
- color: var(--sv-color-text-primary);
71
- border: var(--sv-border-width-hairline) solid var(--sv-color-border);
72
- border-radius: var(--sv-radius-lg);
73
- box-shadow: var(--sv-shadow-overlay);
74
- /* Desktop entrance: fade + gentle scale-up. Same two-phase-mount pattern as
75
- .scrim above. Mobile overrides this to a slide-up instead (below). */
76
- opacity: 0;
77
- transform: scale(0.96);
78
- transition:
79
- opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out),
80
- transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
81
- }
82
-
83
- .panelOpen {
84
- opacity: 1;
85
- transform: scale(1);
86
- }
87
-
88
- /* prefers-reduced-motion: collapse both fade/scale and slide to near-instant.
89
- Not literally 0 — a 0ms transition can skip applying entirely in some
90
- engines, and the JS unmount timer (Dialog.tsx's MOTION_DURATION_MS,
91
- switched to ~0 via usePrefersReducedMotion) needs a transition to still be
92
- "present" for the visual state to actually reach its end value in time. */
93
- @media (prefers-reduced-motion: reduce) {
94
- .scrim,
95
- .panel {
96
- transition-duration: 0.01ms;
97
- }
98
- }
99
-
100
- /* Sizing audit: reviewed padding/radius against this scale's other
101
- surfaces. --sv-radius-lg (shared with Card via .panel below) left
102
- unchanged for the same blast-radius reason as Card.module.css. */
103
- .content {
104
- flex: 1 1 auto;
105
- overflow-y: auto;
106
- overflow-x: hidden;
107
- /* Same slim, token-colored scrollbar as `ScrollArea`/`MessageScroller` —
108
- without this, a `sm`/`md` dialog whose content exceeds its max-height
109
- cap (e.g. on a short viewport where the cap itself shrinks to fit) gets
110
- the browser's default OS scrollbar, which on non-overlay-scrollbar
111
- platforms is wide enough to visually cut into `.panel`'s rounded
112
- corner right where `.content` starts, reading as a layout bug rather
113
- than an intentional scroll affordance. */
114
- scrollbar-width: thin;
115
- scrollbar-color: var(--sv-color-border-strong) transparent;
116
- padding: var(--sv-space-6);
117
- /* This region already supplies the page gutter, so a PageContainer rendered
118
- inside it stands its own down (see PageContainer.module.css). Without
119
- this, an overlay plugin — one page tree rendered into both the Dialog and
120
- the full-page shell fallback — would be padded twice here. */
121
- --sv-page-gutter: 0px;
122
- /* Disable elastic overscroll within the dialog: `none` stops both scroll-
123
- chaining to the parent and the iOS rubber-band bounce inside the panel.
124
- `contain` only prevents chaining — the panel itself still bounces, which
125
- reveals white panel-background between OverlayHeader and the sticky tab
126
- strip on iOS PWA. A dialog is a bounded surface where bounce is a visual
127
- bug, not a feature. */
128
- overscroll-behavior: none;
129
- }
130
-
131
- .content::-webkit-scrollbar {
132
- width: 8px;
133
- }
134
-
135
- .content::-webkit-scrollbar-track {
136
- background: transparent;
137
- }
138
-
139
- .content::-webkit-scrollbar-thumb {
140
- background: var(--sv-color-border-strong);
141
- border-radius: var(--sv-radius-full);
142
- }
143
-
144
- /* `sm`/`md`: fixed width, content-driven height up to the size's own cap
145
- * (28rem/42rem — the box's old fixed heights, now a ceiling rather than a
146
- * floor). `min(<cap>, 100%)` also still caps to the scrim's content box
147
- * (viewport minus margin) so a size never overflows a short viewport. No
148
- * explicit `height` — the panel's flex column sizes to `.content`'s natural
149
- * height on its own; see the file-level comment above. */
150
- .sm {
151
- width: 24rem;
152
- max-width: 100%;
153
- max-height: min(28rem, 100%);
154
- }
155
-
156
- .md {
157
- width: 36rem;
158
- max-width: 100%;
159
- max-height: min(42rem, 100%);
160
- }
161
-
162
- /* Content-driven on both axes, unlike `sm`/`md` (width fixed, only height
163
- * content-driven) — for a dialog whose natural footprint varies a lot (a
164
- * card detail modal with labels/due-date/assignees/description/checklist/
165
- * comments, the case that originally motivated the now-removed `xl` size
166
- * this replaces). `width: fit-content` shrink-wraps to the panel's own
167
- * content (bounded by min/max-width below) the same way a flex item
168
- * centered in `.scrim` naturally would with no explicit `width` at all —
169
- * `min-width` just keeps sparse content (e.g. a short message) from reading
170
- * as an oddly narrow sliver. Caps chosen to span roughly what `sm`/`xl`
171
- * used to cover between them. */
172
- .auto {
173
- width: fit-content;
174
- min-width: min(24rem, 100%);
175
- max-width: min(48rem, 100%);
176
- max-height: min(48rem, 100%);
177
- }
178
-
179
- /* `lg`: a true fixed box, unaffected by the above — see the file-level
180
- * comment. */
181
- .lg {
182
- width: 100%;
183
- height: 100%;
184
- }
185
-
186
- /* `fixed`: also a true fixed box (width AND height both set, like `lg`) but
187
- * capped rather than filling the viewport — see the file-level comment.
188
- * Named distinctly from the dialog's own always-applied `.panel` wrapper
189
- * class above (every size gets `styles.panel` + `styles[size]` together —
190
- * see Dialog.tsx) to avoid colliding with it. `max-width`/`max-height` are
191
- * still needed despite `width`/`height` being fixed rem values, exactly
192
- * like `sm`/`md`'s own `max-width: 100%` — a short or narrow viewport (a
193
- * resized desktop window, not yet at the mobile breakpoint) must still be
194
- * able to shrink this below its rem values instead of overflowing the
195
- * scrim. */
196
- .fixed {
197
- width: 64rem;
198
- max-width: 100%;
199
- height: 44rem;
200
- max-height: 100%;
201
- }
202
-
203
- .close {
204
- position: absolute;
205
- top: var(--sv-space-3);
206
- right: var(--sv-space-3);
207
- /* 2, not 1: a plugin's own sticky in-body header (e.g. a card detail
208
- modal's title row) needs to paint above ordinary scrolling content, so
209
- it sits at z-index: 1 — if `.close` also sat at 1, tree order would
210
- decide the tie, and `.close` (rendered earlier in this component's own
211
- JSX, before `.content` and everything a plugin nests inside it) would
212
- lose to the plugin's later-in-tree header, disappearing underneath it
213
- once they overlap on scroll. 2 keeps `.close` unambiguously on top
214
- without relying on a tie-break plugin authors have no visibility into.
215
- Found live in `sovereign-plugin-kanban`'s card detail modal — see that
216
- repo's `kanban.module.css` `.cardHeader` comment for the matching half
217
- of this fix and the Popover-stacking bug that motivated it. */
218
- z-index: 2;
219
- display: inline-flex;
220
- align-items: center;
221
- justify-content: center;
222
- width: var(--sv-space-8);
223
- height: var(--sv-space-8);
224
- border: none;
225
- border-radius: var(--sv-radius-md);
226
- background: transparent;
227
- color: var(--sv-color-text-muted);
228
- cursor: pointer;
229
- }
230
-
231
- @media (hover: hover) {
232
- .close:hover {
233
- background: var(--sv-color-surface-sunken);
234
- color: var(--sv-color-text-primary);
235
- }
236
- }
237
-
238
- .close:focus-visible {
239
- outline: 2px solid var(--sv-color-focus-ring);
240
- outline-offset: 2px;
241
- }
242
-
243
- /* Hidden on desktop; shown only on mobile where it replaces the close button.
244
- * OverlayHeader owns its own background/border/padding — this wrapper class
245
- * only toggles visibility per breakpoint. Not used at all when the `header`
246
- * prop is active — that OverlayHeader instance renders with no wrapper
247
- * class, so it shows unconditionally on both breakpoints (see Dialog.tsx). */
248
- .mobileHeader {
249
- display: none;
250
- }
251
-
252
- /* The optional `footer` prop's row — shown on both desktop and mobile (no
253
- * breakpoint gating, unlike `.mobileHeader`), a flex sibling after `.content`
254
- * so it never scrolls, mirroring OverlayHeader's own `.header`/`.row`
255
- * treatment (border on the opposite edge, same padding scale) so header and
256
- * footer read as a matched pair when both are present. Layout-agnostic
257
- * beyond that — the footer's own content decides its internal arrangement
258
- * (e.g. a flex row with `justify-content: flex-end` for action buttons). */
259
- .footer {
260
- flex-shrink: 0;
261
- background: var(--sv-color-surface);
262
- border-top: var(--sv-border-width-hairline) solid var(--sv-color-border);
263
- padding: var(--sv-space-3) var(--sv-space-4);
264
- }
265
-
266
- /* Mobile: full-screen sheet (RFC 0001 §3, breakpoint unified to 768px per
267
- * RFC 0013). Every size fills the scrim's available area (which is already
268
- * inset from the top by --sv-dialog-inset-top when a fixed header is shown).
269
- * The panel therefore fills height: 100% of the remaining space, not 100dvh. */
270
- @media (max-width: 768px) {
271
- /* On mobile the overlay feels like a full-page push, not a floating modal.
272
- Remove the dim scrim and panel chrome so it's indistinguishable from a
273
- regular page render. router.back() still closes it correctly.
274
- bottom stops the scrim above the footer nav (matching Drawer) instead of
275
- running the full viewport height — the panel used to extend under the
276
- footer with only .content's own padding compensating for it. */
277
- .scrim {
278
- padding: 0;
279
- background: transparent;
280
- bottom: var(--sv-shell-footer-height, 0);
281
- }
282
-
283
- .panel,
284
- .sm,
285
- .md,
286
- .lg,
287
- .auto,
288
- .fixed {
289
- width: 100%;
290
- height: 100%;
291
- min-width: 0;
292
- max-width: none;
293
- max-height: none;
294
- border: none;
295
- border-radius: 0;
296
- box-shadow: none;
297
- background: var(--sv-color-surface);
298
- }
299
-
300
- /* Mobile entrance is a slide-up, not the desktop fade+scale — matches "page
301
- push" framing above. No opacity change (the panel is opaque full-screen
302
- content, not a floating box), so only transform needs a transition here. */
303
- .panel {
304
- opacity: 1;
305
- transform: translateY(100%);
306
- transition: transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
307
- }
308
-
309
- .panelOpen {
310
- transform: translateY(0);
311
- }
312
-
313
- /* Desktop close button is replaced by OverlayHeader on mobile. */
314
- .close {
315
- display: none;
316
- }
317
-
318
- /* Title + close button in one solid row, via the shared OverlayHeader
319
- component. Being a flex sibling before .content means it never scrolls —
320
- the content area scrolls below it.
321
- .content itself needs no mobile override here any more: it used to zero
322
- out padding-top so a plugin's hand-rolled sticky header (rendered as
323
- .content's own first child, right below OverlayHeader) would sit flush
324
- against it. That case no longer exists — a plugin with a tab strip/
325
- secondary nav now hands it to OverlayHeader's own secondRow slot
326
- (useOverlaySecondRow) instead of rendering it inside .content; Account
327
- and Console both migrated to this (mobile design-system plan, Phase
328
- C1b). With .content's first child back to being genuine page content, it
329
- needs the same breathing room from the header that .content's own base
330
- padding (var(--sv-space-6) on every side) already provides everywhere
331
- else. */
332
- .mobileHeader {
333
- display: block;
334
- }
335
- }