@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,175 +0,0 @@
1
- 'use client';
2
-
3
- import { type PointerEvent as ReactPointerEvent, type ReactNode, useRef } from 'react';
4
- import { useMountTransition, usePrefersReducedMotion } from '../../motion';
5
- import {
6
- OVERLAY_MOTION_DURATION_MS,
7
- useOverlayFocusCapture,
8
- useOverlayKeyboardTrap,
9
- useOverlayScrollLock,
10
- } from '../../overlay-shell';
11
- import { OverlayHeader } from '../OverlayHeader/OverlayHeader';
12
- import styles from './Drawer.module.css';
13
-
14
- export interface DrawerProps {
15
- /** Whether the drawer is shown. When false, nothing renders. */
16
- open: boolean;
17
- /** Called on Esc, scrim click, or a swipe-down past the dismiss threshold. */
18
- onClose: () => void;
19
- /** Accessible name for the drawer panel (sets `aria-label`). */
20
- 'aria-label'?: string;
21
- /** `'content'` (default) sizes to content, capped at 80dvh. `'half'` fixes
22
- * the panel to 50dvh regardless of content — per the design-system's
23
- * "half screen or less" convention for Drawer, this is the only other
24
- * supported size; taller content should use `Sheet` instead. */
25
- snapHeight?: 'content' | 'half';
26
- /** Renders a built-in `OverlayHeader` (title + close) below the grab
27
- * handle. Omit when the content supplies its own header, or none is
28
- * needed at all — e.g. the mobile shell's Apps drawer, whose grab handle
29
- * and swipe-down/scrim-tap dismissal are enough on their own. Mirrors
30
- * `Sheet`'s identical `title` prop. */
31
- title?: string;
32
- children: ReactNode;
33
- }
34
-
35
- // Downward drag distance (px) past which releasing dismisses the drawer
36
- // instead of snapping back open. Distance-only, no velocity tracking — matches
37
- // the swipe-to-reveal gesture already established in consuming plugins (see
38
- // the mobile design-system plan), not a separate technique invented here.
39
- const SWIPE_DISMISS_THRESHOLD_PX = 100;
40
-
41
- /**
42
- * Drawer — a dismissable bottom-sheet panel. Used by the mobile shell for
43
- * plugin navigation; also available to plugins for any bottom-up surface.
44
- *
45
- * Behaviour: Esc, scrim click, or dragging the grab handle down past
46
- * `SWIPE_DISMISS_THRESHOLD_PX` all dismiss; focus moves to the first
47
- * focusable element on open and is restored on close; Tab is trapped within
48
- * the panel. The panel respects `env(safe-area-inset-bottom)` so it clears
49
- * the home indicator in standalone/fullscreen mode. Shares dismissal
50
- * conventions and tokens (`--sv-color-scrim`, `--sv-shadow-overlay`) with
51
- * `Dialog`.
52
- *
53
- * Animated open/close: slides up from the bottom, scrim fades. The `open`/
54
- * `onClose` API is unchanged — closing stays mounted internally for the exit
55
- * transition before actually unmounting; `prefers-reduced-motion: reduce`
56
- * collapses it to near-instant.
57
- *
58
- * The grab handle is the *only* drag-initiation region (not the whole panel)
59
- * — dragging from body content would fight that content's own internal
60
- * scroll, the same reasoning behind the tasks plugin's edge-zone-only
61
- * swipe-to-reveal technique.
62
- */
63
- export function Drawer({
64
- open,
65
- onClose,
66
- 'aria-label': ariaLabel,
67
- snapHeight = 'content',
68
- title,
69
- children,
70
- }: DrawerProps) {
71
- const panelRef = useRef<HTMLDivElement>(null);
72
- const reducedMotion = usePrefersReducedMotion();
73
- const { mounted, phase } = useMountTransition(
74
- open,
75
- reducedMotion ? 0 : OVERLAY_MOTION_DURATION_MS,
76
- );
77
- // Tracks an in-progress handle drag. Kept in a ref (not state) so pointermove
78
- // updates the DOM directly at 60fps instead of re-rendering on every event —
79
- // same technique as the tasks plugin's swipe-to-reveal rows.
80
- const dragStartY = useRef<number | null>(null);
81
-
82
- useOverlayScrollLock(mounted);
83
- useOverlayFocusCapture(panelRef, open);
84
- useOverlayKeyboardTrap(panelRef, open, onClose);
85
-
86
- // Swipe-down-to-dismiss, initiated only from the grab handle (see the
87
- // component doc comment for why not the whole panel). Drags the panel
88
- // directly via inline style while active (transition: none, so it tracks
89
- // the finger 1:1 with no lag) and lets go on release: clearing the inline
90
- // transform in the same commit that re-enables the CSS transition makes
91
- // the panel animate from wherever the drag ended to its resolved position
92
- // — open (snap back) or closed (the exit transition, same as a
93
- // programmatic close) — rather than jump-cutting there. Same technique as
94
- // the tasks plugin's row swipe-to-reveal.
95
- function handleHandlePointerDown(e: ReactPointerEvent) {
96
- e.currentTarget.setPointerCapture(e.pointerId);
97
- dragStartY.current = e.clientY;
98
- }
99
-
100
- function handleHandlePointerMove(e: ReactPointerEvent) {
101
- const startY = dragStartY.current;
102
- if (startY === null) return;
103
- const dy = Math.max(0, e.clientY - startY); // upward drag has no effect — already fully open
104
- const panel = panelRef.current;
105
- if (!panel) return;
106
- panel.style.transition = 'none';
107
- panel.style.transform = `translateY(${dy}px)`;
108
- }
109
-
110
- // Releases the drag and resolves it to open (snap back) or closed, based on
111
- // distance. Shared by pointerup (a completed gesture) and pointercancel
112
- // (the browser took the gesture away, e.g. for a system gesture) — cancel
113
- // always snaps back rather than honoring the distance, since it wasn't a
114
- // deliberate release.
115
- function releaseDrag(e: ReactPointerEvent, honorDistance: boolean) {
116
- const startY = dragStartY.current;
117
- dragStartY.current = null;
118
- if (startY === null) return;
119
- const dy = Math.max(0, e.clientY - startY);
120
- const panel = panelRef.current;
121
- if (panel) {
122
- panel.style.transform = '';
123
- panel.style.transition = '';
124
- }
125
- if (honorDistance && dy > SWIPE_DISMISS_THRESHOLD_PX) onClose();
126
- }
127
-
128
- if (!mounted) return null;
129
- const isOpenPhase = phase === 'open';
130
-
131
- return (
132
- // role="presentation" removes the scrim from the AT (it is purely visual).
133
- // e.target check lets clicks inside the panel bubble without triggering dismiss.
134
- // No onKeyDown here — useOverlayKeyboardTrap above already owns Escape via a
135
- // document-level listener; a second handler here used to double-fire onClose
136
- // per keypress (see Dialog.tsx's identical fix for the full explanation).
137
- <div
138
- className={[styles.scrim, isOpenPhase ? styles.scrimOpen : ''].filter(Boolean).join(' ')}
139
- role="presentation"
140
- onClick={(e) => {
141
- if (e.target === e.currentTarget) onClose();
142
- }}
143
- >
144
- <div
145
- ref={panelRef}
146
- role="dialog"
147
- aria-modal="true"
148
- aria-label={ariaLabel}
149
- tabIndex={-1}
150
- className={[
151
- styles.panel,
152
- snapHeight === 'half' ? styles.panelHalf : '',
153
- isOpenPhase ? styles.panelOpen : '',
154
- ]
155
- .filter(Boolean)
156
- .join(' ')}
157
- >
158
- {/* The only drag-initiation region for swipe-down-to-dismiss — see the
159
- component doc comment for why not the whole panel. Decorative +
160
- functional, so no aria-label of its own; Esc and the scrim remain
161
- the accessible dismiss paths. */}
162
- <div
163
- className={styles.handle}
164
- aria-hidden="true"
165
- onPointerDown={handleHandlePointerDown}
166
- onPointerMove={handleHandlePointerMove}
167
- onPointerUp={(e) => releaseDrag(e, true)}
168
- onPointerCancel={(e) => releaseDrag(e, false)}
169
- />
170
- {title && <OverlayHeader title={title} onClose={onClose} />}
171
- <div className={styles.body}>{children}</div>
172
- </div>
173
- </div>
174
- );
175
- }
@@ -1,226 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, fireEvent, render, screen } from '@testing-library/react';
4
- import { Drawer } from '../Drawer';
5
-
6
- // Drawer's exit animation reads prefers-reduced-motion via matchMedia, which
7
- // jsdom does not implement. `matches: false` (motion enabled) exercises the
8
- // normal animated path; the actual reduced-motion behaviour is covered by
9
- // motion.ts's own tests.
10
- function installMatchMedia() {
11
- vi.stubGlobal(
12
- 'matchMedia',
13
- vi.fn().mockImplementation((query: string) => ({
14
- matches: false,
15
- media: query,
16
- addEventListener: vi.fn(),
17
- removeEventListener: vi.fn(),
18
- addListener: vi.fn(),
19
- removeListener: vi.fn(),
20
- dispatchEvent: vi.fn(),
21
- })),
22
- );
23
- }
24
-
25
- // jsdom does not implement Element.setPointerCapture/releasePointerCapture
26
- // (another documented gap, alongside matchMedia and HTMLDialogElement) — the
27
- // grab handle's pointerdown handler calls setPointerCapture unconditionally.
28
- function installPointerCapture() {
29
- if (!Element.prototype.setPointerCapture) {
30
- Element.prototype.setPointerCapture = () => {};
31
- }
32
- if (!Element.prototype.releasePointerCapture) {
33
- Element.prototype.releasePointerCapture = () => {};
34
- }
35
- }
36
-
37
- describe('Drawer', () => {
38
- beforeEach(() => {
39
- installMatchMedia();
40
- installPointerCapture();
41
- });
42
- afterEach(() => {
43
- vi.unstubAllGlobals();
44
- cleanup();
45
- });
46
-
47
- it('renders nothing when closed', () => {
48
- render(
49
- <Drawer open={false} onClose={() => {}}>
50
- Body
51
- </Drawer>,
52
- );
53
- expect(screen.queryByRole('dialog')).toBeNull();
54
- });
55
-
56
- it('renders the panel with its accessible name when open', () => {
57
- render(
58
- <Drawer open onClose={() => {}} aria-label="Navigation">
59
- Body
60
- </Drawer>,
61
- );
62
- const panel = screen.getByRole('dialog', { name: 'Navigation' });
63
- expect(panel.getAttribute('aria-modal')).toBe('true');
64
- });
65
-
66
- it('calls onClose exactly once on Escape with focus inside the panel', () => {
67
- const onClose = vi.fn();
68
- render(
69
- <Drawer open onClose={onClose} aria-label="Panel">
70
- <button>Focus me</button>
71
- </Drawer>,
72
- );
73
- // Dispatched from the actually-focused element (matching real usage,
74
- // where useOverlayFocusCapture moves focus into the panel on open) so the
75
- // keydown bubbles through the scrim on its way to document — the exact
76
- // path that used to trigger both the scrim's own (now-removed) Escape
77
- // handler and useOverlayKeyboardTrap's document-level listener, double-
78
- // firing onClose. Dispatching straight on `document` (the previous form
79
- // of this test) skips that bubble path and would pass even if the bug
80
- // were reintroduced.
81
- const button = screen.getByRole('button', { name: 'Focus me' });
82
- button.focus();
83
- fireEvent.keyDown(button, { key: 'Escape' });
84
- expect(onClose).toHaveBeenCalledOnce();
85
- });
86
-
87
- it('calls onClose on scrim click but not on panel click', () => {
88
- const onClose = vi.fn();
89
- const { container } = render(
90
- <Drawer open onClose={onClose} aria-label="Nav">
91
- <button>Action</button>
92
- </Drawer>,
93
- );
94
- // The scrim is the outermost div; the panel is a child.
95
- fireEvent.click(screen.getByRole('dialog')); // panel — should not close
96
- expect(onClose).not.toHaveBeenCalled();
97
- // Click the scrim background (the container's first child).
98
- const scrim = container.firstElementChild as HTMLElement;
99
- fireEvent.click(scrim);
100
- expect(onClose).toHaveBeenCalledOnce();
101
- });
102
-
103
- it('applies the half snapHeight class', () => {
104
- render(
105
- <Drawer open onClose={() => {}} aria-label="Nav" snapHeight="half">
106
- Body
107
- </Drawer>,
108
- );
109
- expect(screen.getByRole('dialog').className).toMatch(/panelHalf/);
110
- });
111
-
112
- it('does not apply the half snapHeight class by default (content-sized)', () => {
113
- render(
114
- <Drawer open onClose={() => {}} aria-label="Nav">
115
- Body
116
- </Drawer>,
117
- );
118
- expect(screen.getByRole('dialog').className).not.toMatch(/panelHalf/);
119
- });
120
-
121
- it('does not render OverlayHeader when title is omitted (hidden by default)', () => {
122
- render(
123
- <Drawer open onClose={() => {}} aria-label="Nav">
124
- <button type="button">Own action</button>
125
- </Drawer>,
126
- );
127
- // Only the content's own button — no OverlayHeader close button.
128
- expect(screen.getAllByRole('button')).toHaveLength(1);
129
- });
130
-
131
- it('renders children inside a scrollable body, separate from the grab handle', () => {
132
- // Regression test: the panel used to be the sole scroll container
133
- // (overflow-y: auto on .panel itself), so a tall drawer scrolled the
134
- // grab handle out of view along with the content. The handle must stay
135
- // a sibling of the scrollable region, not a descendant of it.
136
- render(
137
- <Drawer open onClose={() => {}} aria-label="Nav">
138
- <button type="button">Own action</button>
139
- </Drawer>,
140
- );
141
- const panel = screen.getByRole('dialog');
142
- const handle = panel.firstElementChild as HTMLElement;
143
- const button = screen.getByRole('button', { name: 'Own action' });
144
- const body = button.parentElement as HTMLElement;
145
- expect(body).not.toBe(panel);
146
- expect(body.contains(handle)).toBe(false);
147
- expect(panel.contains(body)).toBe(true);
148
- });
149
-
150
- it('renders OverlayHeader (title + close) when title is provided', () => {
151
- const onClose = vi.fn();
152
- render(
153
- <Drawer open onClose={onClose} aria-label="Nav" title="Apps">
154
- Body
155
- </Drawer>,
156
- );
157
- expect(screen.getByText('Apps')).toBeTruthy();
158
- fireEvent.click(screen.getByRole('button', { name: 'Close' }));
159
- expect(onClose).toHaveBeenCalledOnce();
160
- });
161
-
162
- describe('swipe-down-to-dismiss (grab handle)', () => {
163
- // The handle is the panel's first child, aria-hidden and unlabeled —
164
- // same "select via DOM position" approach the scrim-click test above
165
- // already uses for a similarly unlabeled element.
166
- function getHandle() {
167
- return screen.getByRole('dialog').firstElementChild as HTMLElement;
168
- }
169
-
170
- it('dismisses when dragged past the threshold', () => {
171
- const onClose = vi.fn();
172
- render(
173
- <Drawer open onClose={onClose} aria-label="Nav">
174
- Body
175
- </Drawer>,
176
- );
177
- const handle = getHandle();
178
- fireEvent.pointerDown(handle, { clientY: 0 });
179
- fireEvent.pointerMove(handle, { clientY: 150 });
180
- fireEvent.pointerUp(handle, { clientY: 150 }); // 150px > 100px threshold
181
- expect(onClose).toHaveBeenCalledOnce();
182
- });
183
-
184
- it('snaps back without dismissing when released under the threshold', () => {
185
- const onClose = vi.fn();
186
- render(
187
- <Drawer open onClose={onClose} aria-label="Nav">
188
- Body
189
- </Drawer>,
190
- );
191
- const handle = getHandle();
192
- fireEvent.pointerDown(handle, { clientY: 0 });
193
- fireEvent.pointerMove(handle, { clientY: 40 });
194
- fireEvent.pointerUp(handle, { clientY: 40 }); // 40px < 100px threshold
195
- expect(onClose).not.toHaveBeenCalled();
196
- });
197
-
198
- it('snaps back without dismissing on pointercancel, regardless of distance', () => {
199
- const onClose = vi.fn();
200
- render(
201
- <Drawer open onClose={onClose} aria-label="Nav">
202
- Body
203
- </Drawer>,
204
- );
205
- const handle = getHandle();
206
- fireEvent.pointerDown(handle, { clientY: 0 });
207
- fireEvent.pointerMove(handle, { clientY: 200 }); // well past the threshold
208
- fireEvent.pointerCancel(handle, { clientY: 200 });
209
- expect(onClose).not.toHaveBeenCalled();
210
- });
211
-
212
- it('ignores upward drags (already fully open)', () => {
213
- const onClose = vi.fn();
214
- render(
215
- <Drawer open onClose={onClose} aria-label="Nav">
216
- Body
217
- </Drawer>,
218
- );
219
- const handle = getHandle();
220
- fireEvent.pointerDown(handle, { clientY: 100 });
221
- fireEvent.pointerMove(handle, { clientY: 0 }); // upward
222
- fireEvent.pointerUp(handle, { clientY: 0 });
223
- expect(onClose).not.toHaveBeenCalled();
224
- });
225
- });
226
- });
@@ -1,27 +0,0 @@
1
- .root {
2
- display: flex;
3
- flex-direction: column;
4
- align-items: center;
5
- justify-content: center;
6
- gap: var(--sv-space-3);
7
- padding: var(--sv-space-12) var(--sv-space-6);
8
- text-align: center;
9
- }
10
-
11
- .icon {
12
- color: var(--sv-color-text-subtle);
13
- }
14
-
15
- .heading {
16
- margin: 0;
17
- font-size: var(--sv-font-size-md);
18
- font-weight: var(--sv-font-weight-semibold);
19
- color: var(--sv-color-text-primary);
20
- }
21
-
22
- .description {
23
- margin: 0;
24
- font-size: var(--sv-font-size-sm);
25
- color: var(--sv-color-text-muted);
26
- max-width: 36ch;
27
- }
@@ -1,27 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import { Icon } from '../Icon/Icon';
3
- import type { IconName } from '../Icon/Icon';
4
- import styles from './EmptyState.module.css';
5
-
6
- export interface EmptyStateProps {
7
- icon?: IconName;
8
- heading: string;
9
- description?: string;
10
- action?: ReactNode;
11
- className?: string;
12
- }
13
-
14
- export function EmptyState({ icon, heading, description, action, className }: EmptyStateProps) {
15
- return (
16
- <div className={[styles.root, className].filter(Boolean).join(' ')}>
17
- {icon && (
18
- <span className={styles.icon}>
19
- <Icon name={icon} size="lg" aria-hidden={true} />
20
- </span>
21
- )}
22
- <h2 className={styles.heading}>{heading}</h2>
23
- {description && <p className={styles.description}>{description}</p>}
24
- {action}
25
- </div>
26
- );
27
- }
@@ -1,63 +0,0 @@
1
- .dropzone {
2
- display: flex;
3
- align-items: center;
4
- gap: var(--sv-space-4);
5
- width: 100%;
6
- box-sizing: border-box;
7
- padding: var(--sv-space-4) var(--sv-space-5);
8
- border: 1.5px dashed var(--sv-color-border);
9
- border-radius: var(--sv-radius-md);
10
- background-color: var(--sv-color-surface-raised);
11
- cursor: pointer;
12
- transition:
13
- background-color 0.12s ease,
14
- border-color 0.12s ease;
15
- }
16
-
17
- @media (hover: hover) {
18
- .dropzone:hover {
19
- background-color: var(--sv-color-surface-sunken);
20
- border-color: var(--sv-color-border-strong);
21
- }
22
- }
23
-
24
- .dropzoneActive {
25
- background-color: var(--sv-color-surface-sunken);
26
- border-color: var(--sv-color-border-strong);
27
- }
28
-
29
- .dropzoneDisabled {
30
- opacity: 0.5;
31
- cursor: not-allowed;
32
- }
33
-
34
- .icon {
35
- display: inline-flex;
36
- flex-shrink: 0;
37
- color: var(--sv-color-text-muted);
38
- }
39
-
40
- .text {
41
- display: flex;
42
- flex-direction: column;
43
- gap: 2px;
44
- min-width: 0;
45
- }
46
-
47
- .title {
48
- font-size: var(--sv-font-size-sm);
49
- font-weight: var(--sv-font-weight-medium);
50
- color: var(--sv-color-text-primary);
51
- overflow: hidden;
52
- text-overflow: ellipsis;
53
- white-space: nowrap;
54
- }
55
-
56
- .hint {
57
- font-size: var(--sv-font-size-xs);
58
- color: var(--sv-color-text-muted);
59
- }
60
-
61
- .hiddenInput {
62
- display: none;
63
- }
@@ -1,109 +0,0 @@
1
- 'use client';
2
-
3
- import type { DragEvent, ReactNode } from 'react';
4
- import { useRef, useState } from 'react';
5
- import { Icon } from '../Icon/Icon';
6
- import styles from './FileDropzone.module.css';
7
-
8
- export interface FileDropzoneProps {
9
- /** Native `<input type="file">` `name` attribute — set this to submit the
10
- * file as part of a native `<form action={...}>` (Server Action) request. */
11
- name?: string;
12
- /** Native `<input type="file">` `accept` attribute, e.g. `".zip,application/zip"`. */
13
- accept?: string;
14
- /** Icon shown beside the label — a file-type glyph. Defaults to a generic file icon. */
15
- icon?: ReactNode;
16
- /** Primary label — e.g. "Choose a ZIP file", or the selected file's name. */
17
- label: string;
18
- /** Secondary hint — e.g. "or drag and drop here", or the selected file's size. */
19
- hint?: string;
20
- /** Called with the picked or dropped file, or `null` if the input is cleared. */
21
- onFileSelect: (file: File | null) => void;
22
- /** Accessible name for the control — describe what will be uploaded. */
23
- ariaLabel: string;
24
- disabled?: boolean;
25
- className?: string;
26
- }
27
-
28
- /**
29
- * A styled drag-and-drop file picker: a dashed-border dropzone wrapping a
30
- * visually-hidden native `<input type="file">`, so the native picker still
31
- * opens on click and the field participates in normal form semantics. A
32
- * dropped file is written into the input's own `FileList` (via `DataTransfer`)
33
- * so `name` + native `<form action>` submission sees it exactly like a
34
- * click-picked file — not just the `onFileSelect` callback.
35
- *
36
- * Caller owns the selected-file state and passes `label`/`hint` accordingly
37
- * (e.g. swap to the picked file's name/size) — this component is otherwise
38
- * uncontrolled and stateless beyond its own drag-hover visual.
39
- *
40
- * Do not pass `required` through to a wrapping form's validation via this
41
- * field — `display: none` on the hidden input does not exempt it from HTML5
42
- * constraint validation, so a `required` hidden input can block submission
43
- * with no visible field for the user to focus. Validate `onFileSelect`'s
44
- * result in application code instead.
45
- */
46
- export function FileDropzone({
47
- name,
48
- accept,
49
- icon,
50
- label,
51
- hint,
52
- onFileSelect,
53
- ariaLabel,
54
- disabled,
55
- className,
56
- }: FileDropzoneProps) {
57
- const [dragging, setDragging] = useState(false);
58
- const inputRef = useRef<HTMLInputElement>(null);
59
-
60
- return (
61
- <label
62
- className={[
63
- styles.dropzone,
64
- dragging ? styles.dropzoneActive : '',
65
- disabled ? styles.dropzoneDisabled : '',
66
- className,
67
- ]
68
- .filter(Boolean)
69
- .join(' ')}
70
- onDragOver={(event: DragEvent) => {
71
- if (disabled) return;
72
- event.preventDefault();
73
- setDragging(true);
74
- }}
75
- onDragLeave={() => setDragging(false)}
76
- onDrop={(event: DragEvent) => {
77
- if (disabled) return;
78
- event.preventDefault();
79
- setDragging(false);
80
- const dropped = event.dataTransfer.files[0];
81
- if (!dropped) return;
82
- if (inputRef.current && typeof DataTransfer !== 'undefined') {
83
- const transfer = new DataTransfer();
84
- transfer.items.add(dropped);
85
- inputRef.current.files = transfer.files;
86
- }
87
- onFileSelect(dropped);
88
- }}
89
- >
90
- <span className={styles.icon} aria-hidden="true">
91
- {icon ?? <Icon name="file" size="lg" aria-hidden />}
92
- </span>
93
- <span className={styles.text}>
94
- <span className={styles.title}>{label}</span>
95
- {hint && <span className={styles.hint}>{hint}</span>}
96
- </span>
97
- <input
98
- ref={inputRef}
99
- type="file"
100
- name={name}
101
- aria-label={ariaLabel}
102
- accept={accept}
103
- disabled={disabled}
104
- onChange={(event) => onFileSelect(event.target.files?.[0] ?? null)}
105
- className={styles.hiddenInput}
106
- />
107
- </label>
108
- );
109
- }