@sovereignfs/ui 0.54.0 → 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 (473) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/Accordion.module.css +1 -1
  5. package/dist/Alert.module.css +1 -1
  6. package/dist/AppsLauncher.module.css +102 -0
  7. package/dist/Avatar.module.css +1 -1
  8. package/dist/Badge.module.css +30 -7
  9. package/dist/BalanceChip.module.css +1 -1
  10. package/dist/Button.module.css +23 -2
  11. package/dist/Card.module.css +7 -1
  12. package/dist/CardTile.module.css +187 -0
  13. package/dist/CheckableListRow.module.css +8 -0
  14. package/dist/Checkbox.module.css +8 -0
  15. package/dist/CodeTextarea.module.css +7 -1
  16. package/dist/Collapsible.module.css +1 -1
  17. package/dist/ColorPicker.module.css +138 -0
  18. package/dist/Combobox.module.css +8 -2
  19. package/dist/Command.module.css +7 -1
  20. package/dist/ConfirmDialog.module.css +8 -2
  21. package/dist/ConsentPrompt.module.css +21 -0
  22. package/dist/DatePicker.module.css +7 -1
  23. package/dist/Dialog.module.css +130 -21
  24. package/dist/DragHandleRow.module.css +6 -0
  25. package/dist/Drawer.module.css +36 -7
  26. package/dist/FileDropzone.module.css +25 -1
  27. package/dist/Header.module.css +68 -0
  28. package/dist/HeaderFooterLayout.module.css +21 -0
  29. package/dist/IconPicker.module.css +15 -5
  30. package/dist/Input.module.css +7 -1
  31. package/dist/Kbd.module.css +1 -1
  32. package/dist/LegalLinks.module.css +9 -2
  33. package/dist/Markdown.module.css +29 -0
  34. package/dist/Menu.module.css +1 -0
  35. package/dist/Message.module.css +10 -1
  36. package/dist/MessageScroller.module.css +12 -1
  37. package/dist/MobileAppsDrawer.module.css +19 -14
  38. package/dist/MobileFooter.module.css +7 -1
  39. package/dist/MobileHeader.module.css +14 -1
  40. package/dist/NavList.module.css +139 -0
  41. package/dist/NavTabs.module.css +8 -2
  42. package/dist/NotificationsPanel.module.css +268 -0
  43. package/dist/OverlayHeader.module.css +1 -1
  44. package/dist/PageContainer.module.css +62 -0
  45. package/dist/PageHeader.module.css +54 -0
  46. package/dist/PageLayout.module.css +51 -0
  47. package/dist/Popover.module.css +1 -1
  48. package/dist/QrCode.module.css +17 -0
  49. package/dist/QuantityStepper.module.css +5 -3
  50. package/dist/RadioGroup.module.css +6 -0
  51. package/dist/Resizable.module.css +3 -3
  52. package/dist/RootLayout.module.css +12 -0
  53. package/dist/SegmentedControl.module.css +7 -1
  54. package/dist/Select.module.css +7 -1
  55. package/dist/Sheet.module.css +20 -2
  56. package/dist/SplitPane.module.css +5 -5
  57. package/dist/StatusBadge.module.css +1 -1
  58. package/dist/StepStrip.module.css +55 -0
  59. package/dist/SuggestionInput.module.css +14 -3
  60. package/dist/SwipableMobileCarousel.module.css +12 -3
  61. package/dist/SwipableMobileCarouselDots.module.css +21 -0
  62. package/dist/SwipeStack.module.css +101 -0
  63. package/dist/SystemBanner.module.css +16 -0
  64. package/dist/Table.module.css +2 -2
  65. package/dist/Tabs.module.css +7 -1
  66. package/dist/TagInput.module.css +8 -2
  67. package/dist/Textarea.module.css +15 -1
  68. package/dist/ThreeColumnLayout.module.css +35 -0
  69. package/dist/Toast.module.css +67 -3
  70. package/dist/Toggle.module.css +7 -0
  71. package/dist/Tooltip.module.css +7 -1
  72. package/dist/UserMenu.module.css +95 -0
  73. package/dist/fonts/OFL.txt +93 -0
  74. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  75. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  76. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  77. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  78. package/dist/index.d.ts +1156 -76
  79. package/dist/index.js +4223 -1513
  80. package/dist/tokens/fonts.css +53 -0
  81. package/dist/tokens/primitives.css +23 -12
  82. package/dist/tokens/semantic.css +32 -0
  83. package/dist/tokens/theme-presets.css +33 -0
  84. package/dist/tokens.css +2 -1
  85. package/package.json +46 -19
  86. package/src/__tests__/motion.test.tsx +0 -105
  87. package/src/components/Accordion/Accordion.module.css +0 -3
  88. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  89. package/src/components/Accordion/Accordion.tsx +0 -53
  90. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  91. package/src/components/Alert/Alert.module.css +0 -62
  92. package/src/components/Alert/Alert.stories.tsx +0 -96
  93. package/src/components/Alert/Alert.tsx +0 -58
  94. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  95. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  96. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  97. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  98. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  99. package/src/components/Avatar/Avatar.module.css +0 -38
  100. package/src/components/Avatar/Avatar.tsx +0 -42
  101. package/src/components/Badge/Badge.module.css +0 -154
  102. package/src/components/Badge/Badge.stories.tsx +0 -226
  103. package/src/components/Badge/Badge.tsx +0 -81
  104. package/src/components/Badge/__tests__/Badge.test.tsx +0 -88
  105. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  106. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  107. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  108. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  109. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  110. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  111. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  112. package/src/components/Button/Button.module.css +0 -153
  113. package/src/components/Button/Button.stories.tsx +0 -83
  114. package/src/components/Button/Button.tsx +0 -52
  115. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  116. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  117. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  118. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  119. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  120. package/src/components/Calendar/Calendar.module.css +0 -126
  121. package/src/components/Calendar/Calendar.tsx +0 -213
  122. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  123. package/src/components/Calendar/dateUtils.ts +0 -97
  124. package/src/components/Card/Card.module.css +0 -42
  125. package/src/components/Card/Card.tsx +0 -34
  126. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  127. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  128. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  129. package/src/components/Checkbox/Checkbox.module.css +0 -111
  130. package/src/components/Checkbox/Checkbox.tsx +0 -78
  131. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  132. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  133. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  134. package/src/components/Collapsible/Collapsible.module.css +0 -70
  135. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  136. package/src/components/Collapsible/Collapsible.tsx +0 -66
  137. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  138. package/src/components/Combobox/Combobox.module.css +0 -122
  139. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  140. package/src/components/Combobox/Combobox.tsx +0 -186
  141. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  142. package/src/components/Command/Command.module.css +0 -80
  143. package/src/components/Command/Command.stories.tsx +0 -104
  144. package/src/components/Command/Command.tsx +0 -168
  145. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  146. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  147. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -124
  148. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -146
  149. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  150. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  151. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  152. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  153. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  154. package/src/components/DataTable/DataTable.module.css +0 -28
  155. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  156. package/src/components/DataTable/DataTable.tsx +0 -154
  157. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  158. package/src/components/DatePicker/DatePicker.module.css +0 -61
  159. package/src/components/DatePicker/DatePicker.tsx +0 -103
  160. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  161. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  162. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  163. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  164. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  165. package/src/components/Dialog/Dialog.module.css +0 -226
  166. package/src/components/Dialog/Dialog.stories.tsx +0 -147
  167. package/src/components/Dialog/Dialog.tsx +0 -160
  168. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -137
  169. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  170. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -61
  171. package/src/components/Drawer/Drawer.module.css +0 -92
  172. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  173. package/src/components/Drawer/Drawer.tsx +0 -176
  174. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -199
  175. package/src/components/EmptyState/EmptyState.module.css +0 -27
  176. package/src/components/EmptyState/EmptyState.tsx +0 -27
  177. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  178. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  179. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  180. package/src/components/FormField/FormField.module.css +0 -33
  181. package/src/components/FormField/FormField.tsx +0 -78
  182. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  183. package/src/components/HoverCard/HoverCard.module.css +0 -3
  184. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  185. package/src/components/HoverCard/HoverCard.tsx +0 -111
  186. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  187. package/src/components/Icon/Icon.module.css +0 -27
  188. package/src/components/Icon/Icon.stories.tsx +0 -95
  189. package/src/components/Icon/Icon.tsx +0 -43
  190. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  191. package/src/components/Icon/icons/activity.tsx +0 -20
  192. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  193. package/src/components/Icon/icons/apple.tsx +0 -21
  194. package/src/components/Icon/icons/banana.tsx +0 -21
  195. package/src/components/Icon/icons/beef.tsx +0 -22
  196. package/src/components/Icon/icons/beer.tsx +0 -24
  197. package/src/components/Icon/icons/bell.tsx +0 -21
  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-x.tsx +0 -22
  208. package/src/components/Icon/icons/coffee.tsx +0 -23
  209. package/src/components/Icon/icons/cookie.tsx +0 -25
  210. package/src/components/Icon/icons/croissant.tsx +0 -24
  211. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  212. package/src/components/Icon/icons/drumstick.tsx +0 -21
  213. package/src/components/Icon/icons/egg.tsx +0 -20
  214. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  215. package/src/components/Icon/icons/external-link.tsx +0 -22
  216. package/src/components/Icon/icons/eye-off.tsx +0 -23
  217. package/src/components/Icon/icons/eye.tsx +0 -21
  218. package/src/components/Icon/icons/file.tsx +0 -21
  219. package/src/components/Icon/icons/fish.tsx +0 -25
  220. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  221. package/src/components/Icon/icons/house.tsx +0 -21
  222. package/src/components/Icon/icons/index.ts +0 -234
  223. package/src/components/Icon/icons/info.tsx +0 -22
  224. package/src/components/Icon/icons/lock.tsx +0 -21
  225. package/src/components/Icon/icons/log-out.tsx +0 -22
  226. package/src/components/Icon/icons/mail.tsx +0 -21
  227. package/src/components/Icon/icons/menu.tsx +0 -22
  228. package/src/components/Icon/icons/milk.tsx +0 -22
  229. package/src/components/Icon/icons/package.tsx +0 -23
  230. package/src/components/Icon/icons/pencil.tsx +0 -21
  231. package/src/components/Icon/icons/pizza.tsx +0 -24
  232. package/src/components/Icon/icons/plus.tsx +0 -21
  233. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  234. package/src/components/Icon/icons/salad.tsx +0 -24
  235. package/src/components/Icon/icons/search.tsx +0 -21
  236. package/src/components/Icon/icons/settings.tsx +0 -21
  237. package/src/components/Icon/icons/shield.tsx +0 -20
  238. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  239. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  240. package/src/components/Icon/icons/smartphone.tsx +0 -21
  241. package/src/components/Icon/icons/snowflake.tsx +0 -31
  242. package/src/components/Icon/icons/spray-can.tsx +0 -29
  243. package/src/components/Icon/icons/trash-2.tsx +0 -24
  244. package/src/components/Icon/icons/upload.tsx +0 -22
  245. package/src/components/Icon/icons/user.tsx +0 -21
  246. package/src/components/Icon/icons/wine.tsx +0 -23
  247. package/src/components/Icon/icons/x.tsx +0 -21
  248. package/src/components/IconPicker/IconPicker.module.css +0 -63
  249. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  250. package/src/components/IconPicker/IconPicker.tsx +0 -90
  251. package/src/components/Input/Input.module.css +0 -52
  252. package/src/components/Input/Input.stories.tsx +0 -86
  253. package/src/components/Input/Input.tsx +0 -14
  254. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  255. package/src/components/Item/Item.module.css +0 -70
  256. package/src/components/Item/Item.stories.tsx +0 -62
  257. package/src/components/Item/Item.tsx +0 -54
  258. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  259. package/src/components/Kbd/Kbd.module.css +0 -14
  260. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  261. package/src/components/Kbd/Kbd.tsx +0 -12
  262. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  263. package/src/components/Label/Label.module.css +0 -11
  264. package/src/components/Label/Label.stories.tsx +0 -40
  265. package/src/components/Label/Label.tsx +0 -24
  266. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  267. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  268. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  269. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  270. package/src/components/Markdown/Markdown.module.css +0 -49
  271. package/src/components/Markdown/Markdown.stories.tsx +0 -30
  272. package/src/components/Markdown/Markdown.tsx +0 -168
  273. package/src/components/Marker/Marker.module.css +0 -33
  274. package/src/components/Marker/Marker.stories.tsx +0 -39
  275. package/src/components/Marker/Marker.tsx +0 -34
  276. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  277. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  278. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  279. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  280. package/src/components/Menu/Menu.module.css +0 -89
  281. package/src/components/Menu/Menu.tsx +0 -159
  282. package/src/components/Menu/__tests__/Menu.test.tsx +0 -197
  283. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  284. package/src/components/Menubar/Menubar.tsx +0 -42
  285. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  286. package/src/components/Message/Message.module.css +0 -99
  287. package/src/components/Message/Message.stories.tsx +0 -79
  288. package/src/components/Message/Message.tsx +0 -41
  289. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  290. package/src/components/MessageScroller/MessageScroller.module.css +0 -54
  291. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  292. package/src/components/MessageScroller/MessageScroller.tsx +0 -72
  293. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  294. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -81
  295. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  296. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  297. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  298. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  299. package/src/components/MobileFooter/MobileFooter.tsx +0 -109
  300. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -71
  301. package/src/components/MobileHeader/MobileHeader.module.css +0 -63
  302. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  303. package/src/components/MobileHeader/MobileHeader.tsx +0 -77
  304. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -58
  305. package/src/components/NavTabs/NavTabs.module.css +0 -50
  306. package/src/components/NavTabs/NavTabs.tsx +0 -61
  307. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  308. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  309. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  310. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  311. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  312. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  313. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  314. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -62
  315. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -51
  316. package/src/components/PageContainer/PageContainer.module.css +0 -20
  317. package/src/components/PageContainer/PageContainer.tsx +0 -31
  318. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -37
  319. package/src/components/PageHeader/PageHeader.module.css +0 -32
  320. package/src/components/PageHeader/PageHeader.tsx +0 -35
  321. package/src/components/Pagination/Pagination.module.css +0 -98
  322. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  323. package/src/components/Pagination/Pagination.tsx +0 -87
  324. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  325. package/src/components/Popover/Popover.module.css +0 -74
  326. package/src/components/Popover/Popover.stories.tsx +0 -357
  327. package/src/components/Popover/Popover.tsx +0 -208
  328. package/src/components/Popover/__tests__/Popover.test.tsx +0 -98
  329. package/src/components/Progress/Progress.module.css +0 -20
  330. package/src/components/Progress/Progress.stories.tsx +0 -40
  331. package/src/components/Progress/Progress.tsx +0 -35
  332. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  333. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  334. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  335. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  336. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  337. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  338. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  339. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  340. package/src/components/Resizable/Resizable.module.css +0 -70
  341. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  342. package/src/components/Resizable/Resizable.tsx +0 -313
  343. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  344. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  345. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  346. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  347. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  348. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  349. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  350. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  351. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  352. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  353. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  354. package/src/components/Select/Select.module.css +0 -82
  355. package/src/components/Select/Select.stories.tsx +0 -115
  356. package/src/components/Select/Select.tsx +0 -48
  357. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  358. package/src/components/Sheet/Sheet.module.css +0 -55
  359. package/src/components/Sheet/Sheet.tsx +0 -109
  360. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  361. package/src/components/Slider/Slider.module.css +0 -95
  362. package/src/components/Slider/Slider.stories.tsx +0 -64
  363. package/src/components/Slider/Slider.tsx +0 -77
  364. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  365. package/src/components/Spinner/Spinner.module.css +0 -39
  366. package/src/components/Spinner/Spinner.tsx +0 -23
  367. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  368. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  369. package/src/components/SplitPane/SplitPane.module.css +0 -85
  370. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  371. package/src/components/SplitPane/SplitPane.tsx +0 -149
  372. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  373. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  374. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  375. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  376. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  377. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  378. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  379. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -55
  380. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -227
  381. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  382. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  383. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  384. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  385. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  386. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -133
  387. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  388. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  389. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -49
  390. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -62
  391. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  392. package/src/components/SystemBanner/SystemBanner.module.css +0 -69
  393. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  394. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  395. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  396. package/src/components/Table/Table.module.css +0 -45
  397. package/src/components/Table/Table.stories.tsx +0 -125
  398. package/src/components/Table/Table.tsx +0 -51
  399. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  400. package/src/components/Tabs/Tabs.module.css +0 -56
  401. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  402. package/src/components/Tabs/Tabs.tsx +0 -46
  403. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  404. package/src/components/TagInput/TagInput.module.css +0 -141
  405. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  406. package/src/components/TagInput/TagInput.tsx +0 -174
  407. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  408. package/src/components/Textarea/Textarea.module.css +0 -39
  409. package/src/components/Textarea/Textarea.tsx +0 -15
  410. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -29
  411. package/src/components/Toast/Toast.module.css +0 -132
  412. package/src/components/Toast/Toast.stories.tsx +0 -191
  413. package/src/components/Toast/Toast.tsx +0 -139
  414. package/src/components/Toggle/Toggle.module.css +0 -57
  415. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  416. package/src/components/Toggle/Toggle.tsx +0 -39
  417. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  418. package/src/components/Tooltip/Tooltip.module.css +0 -56
  419. package/src/components/Tooltip/Tooltip.tsx +0 -30
  420. package/src/components/Typography/Typography.module.css +0 -47
  421. package/src/components/Typography/Typography.stories.tsx +0 -62
  422. package/src/components/Typography/Typography.tsx +0 -30
  423. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  424. package/src/css-modules.d.ts +0 -4
  425. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  426. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  427. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  428. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  429. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  430. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  431. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  432. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -93
  433. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  434. package/src/hooks/index.ts +0 -24
  435. package/src/hooks/useCarouselRouteSync.ts +0 -92
  436. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  437. package/src/hooks/useDoubleTap.ts +0 -91
  438. package/src/hooks/useIsMobile.ts +0 -33
  439. package/src/hooks/useIsOffline.ts +0 -41
  440. package/src/hooks/useLongPress.ts +0 -185
  441. package/src/hooks/useOfflineTileState.ts +0 -45
  442. package/src/hooks/useResponsiveLayout.ts +0 -36
  443. package/src/hooks/useSnapCarousel.ts +0 -79
  444. package/src/hooks/useSwipeReveal.ts +0 -107
  445. package/src/index.ts +0 -251
  446. package/src/motion.ts +0 -78
  447. package/src/overlay-shell.ts +0 -94
  448. package/src/scroll-lock.ts +0 -22
  449. package/src/stories/Avatar.stories.tsx +0 -44
  450. package/src/stories/Card.stories.tsx +0 -35
  451. package/src/stories/Checkbox.stories.tsx +0 -45
  452. package/src/stories/DesignSystemOverview.stories.tsx +0 -3187
  453. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  454. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  455. package/src/stories/DragHandleRow.stories.tsx +0 -41
  456. package/src/stories/EmptyState.stories.tsx +0 -33
  457. package/src/stories/FileDropzone.stories.tsx +0 -69
  458. package/src/stories/FormField.stories.tsx +0 -47
  459. package/src/stories/InteractionHooks.stories.tsx +0 -925
  460. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  461. package/src/stories/NavTabs.stories.tsx +0 -53
  462. package/src/stories/OfflineGate.stories.tsx +0 -42
  463. package/src/stories/PageContainer.stories.tsx +0 -37
  464. package/src/stories/PageHeader.stories.tsx +0 -42
  465. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  466. package/src/stories/Spinner.stories.tsx +0 -25
  467. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -304
  468. package/src/stories/Textarea.stories.tsx +0 -51
  469. package/src/stories/TokenGallery.stories.tsx +0 -602
  470. package/src/stories/Tooltip.stories.tsx +0 -59
  471. package/src/tokens/primitives.css +0 -157
  472. package/src/tokens/semantic.css +0 -130
  473. package/src/tokens.css +0 -5
@@ -1,70 +0,0 @@
1
- .group {
2
- display: flex;
3
- flex-direction: row;
4
- width: 100%;
5
- height: 100%;
6
- min-height: 320px;
7
- border: 1px solid var(--sv-color-border);
8
- border-radius: var(--sv-radius-lg);
9
- overflow: hidden;
10
- background: var(--sv-color-surface);
11
- }
12
-
13
- .groupVertical {
14
- flex-direction: column;
15
- }
16
-
17
- .panel {
18
- min-width: 0;
19
- min-height: 0;
20
- overflow: auto;
21
- background: var(--sv-color-surface);
22
- }
23
-
24
- .handle {
25
- position: relative;
26
- flex-shrink: 0;
27
- width: 12px;
28
- padding: 0;
29
- border: 0;
30
- border-inline: 1px solid var(--sv-color-border);
31
- cursor: col-resize;
32
- background: var(--sv-color-surface-sunken);
33
- }
34
-
35
- .handleVertical {
36
- width: 100%;
37
- height: 12px;
38
- border-inline: 0;
39
- border-block: 1px solid var(--sv-color-border);
40
- cursor: row-resize;
41
- }
42
-
43
- .handle::before {
44
- position: absolute;
45
- inset-block: 50%;
46
- inset-inline: 50%;
47
- width: 2px;
48
- height: 40px;
49
- content: '';
50
- background: var(--sv-color-border-strong);
51
- border-radius: var(--sv-radius-full);
52
- transform: translate(-50%, -50%);
53
- }
54
-
55
- .handleVertical::before {
56
- width: 40px;
57
- height: 2px;
58
- }
59
-
60
- @media (hover: hover) {
61
- .handle:hover {
62
- background: var(--sv-color-accent-subtle);
63
- }
64
- }
65
-
66
- .handle:focus-visible {
67
- background: var(--sv-color-accent-subtle);
68
- outline: 2px solid var(--sv-color-focus-ring);
69
- outline-offset: -2px;
70
- }
@@ -1,82 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from './Resizable';
3
-
4
- const meta = {
5
- title: 'Components/Resizable',
6
- component: ResizablePanelGroup,
7
- parameters: {
8
- layout: 'padded',
9
- docs: {
10
- description: {
11
- component:
12
- 'A row or column of resizable panes. Each handle resizes only its two immediate neighbor panels, clamped to their own min/max. Desktop-oriented — panels render at their default sizes on touch.',
13
- },
14
- },
15
- },
16
- args: { direction: 'horizontal', children: null },
17
- } satisfies Meta<typeof ResizablePanelGroup>;
18
-
19
- export default meta;
20
- type Story = StoryObj<typeof meta>;
21
-
22
- // ---------------------------------------------------------------------------
23
-
24
- const paneStyle: React.CSSProperties = {
25
- display: 'flex',
26
- alignItems: 'center',
27
- justifyContent: 'center',
28
- height: '100%',
29
- padding: 'var(--sv-space-4)',
30
- fontSize: 14,
31
- color: 'var(--sv-color-text-muted)',
32
- };
33
-
34
- export const Horizontal: Story = {
35
- render: () => (
36
- <ResizablePanelGroup direction="horizontal">
37
- <ResizablePanel defaultSize={25} minSize={15} maxSize={50}>
38
- <div style={paneStyle}>Sidebar</div>
39
- </ResizablePanel>
40
- <ResizableHandle aria-label="Resize sidebar" />
41
- <ResizablePanel defaultSize={75}>
42
- <div style={paneStyle}>Content</div>
43
- </ResizablePanel>
44
- </ResizablePanelGroup>
45
- ),
46
- };
47
-
48
- export const ThreePanels: Story = {
49
- render: () => (
50
- <ResizablePanelGroup direction="horizontal">
51
- <ResizablePanel defaultSize={20} minSize={15} maxSize={40}>
52
- <div style={paneStyle}>Files</div>
53
- </ResizablePanel>
54
- <ResizableHandle aria-label="Resize files panel" />
55
- <ResizablePanel defaultSize={50}>
56
- <div style={paneStyle}>Editor</div>
57
- </ResizablePanel>
58
- <ResizableHandle aria-label="Resize editor panel" />
59
- <ResizablePanel defaultSize={30} minSize={15} maxSize={50}>
60
- <div style={paneStyle}>Preview</div>
61
- </ResizablePanel>
62
- </ResizablePanelGroup>
63
- ),
64
- };
65
-
66
- export const Vertical: Story = {
67
- render: () => (
68
- // Vertical orientation needs a definite-height ancestor for the
69
- // percentage-based flex-basis on each panel to resolve.
70
- <div style={{ height: 400 }}>
71
- <ResizablePanelGroup direction="vertical">
72
- <ResizablePanel defaultSize={30}>
73
- <div style={paneStyle}>Console output</div>
74
- </ResizablePanel>
75
- <ResizableHandle aria-label="Resize console" />
76
- <ResizablePanel defaultSize={70}>
77
- <div style={paneStyle}>Editor</div>
78
- </ResizablePanel>
79
- </ResizablePanelGroup>
80
- </div>
81
- ),
82
- };
@@ -1,313 +0,0 @@
1
- 'use client';
2
-
3
- import { Children, isValidElement, useEffect, useRef, useState } from 'react';
4
- import type {
5
- CSSProperties,
6
- KeyboardEvent as ReactKeyboardEvent,
7
- PointerEvent as ReactPointerEvent,
8
- ReactElement,
9
- ReactNode,
10
- } from 'react';
11
- import styles from './Resizable.module.css';
12
-
13
- export type ResizableDirection = 'horizontal' | 'vertical';
14
-
15
- export interface ResizablePanelProps {
16
- /** Initial size as a percentage of the group's main axis. Defaults to an
17
- * equal split across all panels in the group. */
18
- defaultSize?: number;
19
- /** Minimum size as a percentage. Defaults to 10. */
20
- minSize?: number;
21
- /** Maximum size as a percentage. Defaults to 90. */
22
- maxSize?: number;
23
- children?: ReactNode;
24
- className?: string;
25
- /** Injected by ResizablePanelGroup — not part of the public API. */
26
- style?: CSSProperties;
27
- }
28
-
29
- /** One pane of a ResizablePanelGroup. Sizing is computed and injected by the
30
- * group (via defaultSize/minSize/maxSize read off this element's props) —
31
- * this component only renders the scrollable content box. */
32
- export function ResizablePanel({ children, className, style }: ResizablePanelProps) {
33
- return (
34
- <div className={[styles.panel, className].filter(Boolean).join(' ')} style={style}>
35
- {children}
36
- </div>
37
- );
38
- }
39
-
40
- export interface ResizableHandleProps {
41
- 'aria-label'?: string;
42
- /** Injected by ResizablePanelGroup — not part of the public API. */
43
- direction?: ResizableDirection;
44
- onPointerDown?: (e: ReactPointerEvent<HTMLDivElement>) => void;
45
- onKeyDown?: (e: ReactKeyboardEvent<HTMLDivElement>) => void;
46
- 'aria-valuenow'?: number;
47
- 'aria-valuemin'?: number;
48
- 'aria-valuemax'?: number;
49
- }
50
-
51
- /** The draggable divider between two ResizablePanels. Placed directly
52
- * between the two ResizablePanel elements it resizes — the group pairs each
53
- * handle with its preceding and following panel by position.
54
- *
55
- * A `div` with `role="separator"` and `tabIndex=0` (the WAI-ARIA "window
56
- * splitter" pattern), not a `<button>` — `separator` is a non-interactive
57
- * role, and a native button's implicit role can't be overridden to it. */
58
- export function ResizableHandle({
59
- 'aria-label': ariaLabel = 'Resize panels',
60
- direction = 'horizontal',
61
- onPointerDown,
62
- onKeyDown,
63
- 'aria-valuenow': valueNow,
64
- 'aria-valuemin': valueMin,
65
- 'aria-valuemax': valueMax,
66
- }: ResizableHandleProps) {
67
- return (
68
- /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex -- WAI-ARIA "window splitter" pattern: a focusable, keyboard-operable separator is the documented exception to role="separator" being non-interactive (https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/). */
69
- <div
70
- className={[styles.handle, direction === 'vertical' ? styles.handleVertical : '']
71
- .filter(Boolean)
72
- .join(' ')}
73
- role="separator"
74
- tabIndex={0}
75
- aria-orientation={direction === 'horizontal' ? 'vertical' : 'horizontal'}
76
- aria-label={ariaLabel}
77
- aria-valuenow={valueNow !== undefined ? Math.round(valueNow) : undefined}
78
- aria-valuemin={valueMin}
79
- aria-valuemax={valueMax}
80
- onPointerDown={onPointerDown}
81
- onKeyDown={onKeyDown}
82
- />
83
- /* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
84
- );
85
- }
86
-
87
- export interface ResizablePanelGroupProps {
88
- direction: ResizableDirection;
89
- /** Alternating ResizablePanel / ResizableHandle elements — N panels
90
- * separated by N-1 handles. */
91
- children: ReactNode;
92
- className?: string;
93
- }
94
-
95
- interface PanelConstraint {
96
- defaultSize: number;
97
- minSize: number;
98
- maxSize: number;
99
- }
100
-
101
- const clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);
102
-
103
- /**
104
- * ResizablePanelGroup — a row or column of resizable panes (editor layouts,
105
- * multi-pane inspectors). Each handle resizes only its two immediate
106
- * neighbor panels (drag redistributes size between them, clamped to both
107
- * panels' own min/max, so their combined size is a fixed invariant for the
108
- * duration of one drag) — the same handle-local model most resizable-panel
109
- * implementations use, rather than redistributing across the whole group.
110
- *
111
- * Desktop-oriented, like NavigationMenu — a drag handle has no direct touch
112
- * equivalent; panels render at their default sizes on touch rather than
113
- * attempting a redesign no consumer has asked for yet. For a two-pane
114
- * layout that also needs a mobile single-column fallback, use SplitPane
115
- * instead.
116
- *
117
- * `direction="vertical"` needs a definite-height ancestor — percentage
118
- * flex-basis on a column's children only resolves against one.
119
- */
120
- export function ResizablePanelGroup({ direction, children, className }: ResizablePanelGroupProps) {
121
- const elements = Children.toArray(children).filter(isValidElement) as ReactElement<
122
- ResizablePanelProps | ResizableHandleProps
123
- >[];
124
- const panelCount = elements.filter((el) => el.type === ResizablePanel).length;
125
-
126
- const constraints: PanelConstraint[] = elements
127
- .filter((el) => el.type === ResizablePanel)
128
- .map((el) => {
129
- const props = el.props as ResizablePanelProps;
130
- return {
131
- defaultSize: props.defaultSize ?? 100 / panelCount,
132
- minSize: props.minSize ?? 10,
133
- maxSize: props.maxSize ?? 90,
134
- };
135
- });
136
-
137
- const [sizes, setSizes] = useState<number[]>(() => constraints.map((c) => c.defaultSize));
138
-
139
- // A different set of panels rendered (count changed) — re-derive rather
140
- // than keep stale entries. Legal "adjust state during render" pattern;
141
- // sizes.length matches constraints.length again on the next render, so
142
- // this cannot loop.
143
- if (sizes.length !== constraints.length) {
144
- setSizes(constraints.map((c) => c.defaultSize));
145
- }
146
-
147
- const containerRef = useRef<HTMLDivElement>(null);
148
- // Always-latest refs so the window-level pointer listeners (registered
149
- // once, see below) never read stale values without needing to be
150
- // re-registered on every render.
151
- const constraintsRef = useRef(constraints);
152
- constraintsRef.current = constraints;
153
- const directionRef = useRef(direction);
154
- directionRef.current = direction;
155
-
156
- const dragState = useRef<{
157
- handleIndex: number;
158
- pointerId: number;
159
- startPos: number;
160
- startA: number;
161
- combined: number;
162
- } | null>(null);
163
-
164
- function applyResize(handleIndex: number, nextA: number, combined: number) {
165
- const a = constraintsRef.current[handleIndex];
166
- const b = constraintsRef.current[handleIndex + 1];
167
- if (!a || !b) return;
168
- const clampedA = clamp(
169
- nextA,
170
- Math.max(a.minSize, combined - b.maxSize),
171
- Math.min(a.maxSize, combined - b.minSize),
172
- );
173
- setSizes((prev) => {
174
- const next = [...prev];
175
- next[handleIndex] = clampedA;
176
- next[handleIndex + 1] = combined - clampedA;
177
- return next;
178
- });
179
- }
180
-
181
- useEffect(() => {
182
- function handlePointerMove(event: globalThis.PointerEvent) {
183
- const drag = dragState.current;
184
- const rect = containerRef.current?.getBoundingClientRect();
185
- if (!drag || !rect || event.pointerId !== drag.pointerId) return;
186
- const size = directionRef.current === 'horizontal' ? rect.width : rect.height;
187
- if (size === 0) return;
188
- const pos = directionRef.current === 'horizontal' ? event.clientX : event.clientY;
189
- const deltaPercent = ((pos - drag.startPos) / size) * 100;
190
- applyResize(drag.handleIndex, drag.startA + deltaPercent, drag.combined);
191
- }
192
-
193
- function stopDragging(event: globalThis.PointerEvent) {
194
- if (!dragState.current || event.pointerId !== dragState.current.pointerId) return;
195
- dragState.current = null;
196
- document.body.style.cursor = '';
197
- document.body.style.userSelect = '';
198
- }
199
-
200
- window.addEventListener('pointermove', handlePointerMove);
201
- window.addEventListener('pointerup', stopDragging);
202
- window.addEventListener('pointercancel', stopDragging);
203
- return () => {
204
- window.removeEventListener('pointermove', handlePointerMove);
205
- window.removeEventListener('pointerup', stopDragging);
206
- window.removeEventListener('pointercancel', stopDragging);
207
- document.body.style.cursor = '';
208
- document.body.style.userSelect = '';
209
- };
210
- // Registered once — handlePointerMove reads live state via refs instead
211
- // of closing over props/state that would otherwise need to be deps.
212
- }, []);
213
-
214
- function startDragging(handleIndex: number, event: ReactPointerEvent<HTMLDivElement>) {
215
- const startA = sizes[handleIndex] ?? 0;
216
- const startB = sizes[handleIndex + 1] ?? 0;
217
- dragState.current = {
218
- handleIndex,
219
- pointerId: event.pointerId,
220
- startPos: direction === 'horizontal' ? event.clientX : event.clientY,
221
- startA,
222
- combined: startA + startB,
223
- };
224
- document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize';
225
- document.body.style.userSelect = 'none';
226
- event.currentTarget.setPointerCapture(event.pointerId);
227
- }
228
-
229
- function resizeWithKeyboard(handleIndex: number, event: ReactKeyboardEvent<HTMLDivElement>) {
230
- const step = event.shiftKey ? 10 : 5;
231
- const forwardKey = direction === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
232
- const backwardKey = direction === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
233
- const sizeA = sizes[handleIndex] ?? 0;
234
- const sizeB = sizes[handleIndex + 1] ?? 0;
235
- const combined = sizeA + sizeB;
236
- if (event.key === forwardKey) {
237
- event.preventDefault();
238
- applyResize(handleIndex, sizeA + step, combined);
239
- } else if (event.key === backwardKey) {
240
- event.preventDefault();
241
- applyResize(handleIndex, sizeA - step, combined);
242
- }
243
- }
244
-
245
- let panelIndex = -1;
246
- let handleIndex = -1;
247
-
248
- return (
249
- <div
250
- ref={containerRef}
251
- className={[styles.group, direction === 'vertical' ? styles.groupVertical : '', className]
252
- .filter(Boolean)
253
- .join(' ')}
254
- >
255
- {elements.map((element, key) => {
256
- if (element.type === ResizablePanel) {
257
- panelIndex += 1;
258
- const size = sizes[panelIndex] ?? constraints[panelIndex]?.defaultSize ?? 0;
259
- return (
260
- <ResizablePanelClone
261
- key={key}
262
- element={element as ReactElement<ResizablePanelProps>}
263
- flexBasis={size}
264
- />
265
- );
266
- }
267
- if (element.type === ResizableHandle) {
268
- handleIndex += 1;
269
- const index = handleIndex;
270
- const constraint = constraints[index];
271
- return (
272
- <ResizableHandleClone
273
- key={key}
274
- element={element as ReactElement<ResizableHandleProps>}
275
- direction={direction}
276
- aria-valuenow={sizes[index]}
277
- aria-valuemin={constraint?.minSize}
278
- aria-valuemax={constraint?.maxSize}
279
- onPointerDown={(e) => startDragging(index, e)}
280
- onKeyDown={(e) => resizeWithKeyboard(index, e)}
281
- />
282
- );
283
- }
284
- return element;
285
- })}
286
- </div>
287
- );
288
- }
289
-
290
- function ResizablePanelClone({
291
- element,
292
- flexBasis,
293
- }: {
294
- element: ReactElement<ResizablePanelProps>;
295
- flexBasis: number;
296
- }) {
297
- const style: CSSProperties = {
298
- ...element.props.style,
299
- flexBasis: `${flexBasis}%`,
300
- flexGrow: 0,
301
- flexShrink: 0,
302
- };
303
- return <ResizablePanel {...element.props} style={style} />;
304
- }
305
-
306
- function ResizableHandleClone({
307
- element,
308
- ...injected
309
- }: {
310
- element: ReactElement<ResizableHandleProps>;
311
- } & ResizableHandleProps) {
312
- return <ResizableHandle {...element.props} {...injected} />;
313
- }
@@ -1,128 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import { cleanup, fireEvent, render, screen } from '@testing-library/react';
4
- import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '../Resizable';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('ResizablePanelGroup', () => {
9
- it('renders each panel and a separator between them', () => {
10
- render(
11
- <ResizablePanelGroup direction="horizontal">
12
- <ResizablePanel>
13
- <p>Left</p>
14
- </ResizablePanel>
15
- <ResizableHandle aria-label="Resize sidebar" />
16
- <ResizablePanel>
17
- <p>Right</p>
18
- </ResizablePanel>
19
- </ResizablePanelGroup>,
20
- );
21
-
22
- expect(screen.getByText('Left')).toBeDefined();
23
- expect(screen.getByText('Right')).toBeDefined();
24
- expect(screen.getByRole('separator', { name: 'Resize sidebar' })).toBeDefined();
25
- });
26
-
27
- it('splits panels evenly by default', () => {
28
- render(
29
- <ResizablePanelGroup direction="horizontal">
30
- <ResizablePanel>
31
- <p>Left</p>
32
- </ResizablePanel>
33
- <ResizableHandle aria-label="Resize" />
34
- <ResizablePanel>
35
- <p>Right</p>
36
- </ResizablePanel>
37
- </ResizablePanelGroup>,
38
- );
39
-
40
- const separator = screen.getByRole('separator', { name: 'Resize' });
41
- expect(separator.getAttribute('aria-valuenow')).toBe('50');
42
- });
43
-
44
- it('resizes the pair of neighboring panels with the keyboard, redistributing their combined size', () => {
45
- render(
46
- <ResizablePanelGroup direction="horizontal">
47
- <ResizablePanel defaultSize={50} minSize={20} maxSize={80}>
48
- <p>Left</p>
49
- </ResizablePanel>
50
- <ResizableHandle aria-label="Resize" />
51
- <ResizablePanel defaultSize={50} minSize={20} maxSize={80}>
52
- <p>Right</p>
53
- </ResizablePanel>
54
- </ResizablePanelGroup>,
55
- );
56
-
57
- const separator = screen.getByRole('separator', { name: 'Resize' });
58
- fireEvent.keyDown(separator, { key: 'ArrowRight' });
59
- expect(separator.getAttribute('aria-valuenow')).toBe('55');
60
-
61
- fireEvent.keyDown(separator, { key: 'ArrowLeft', shiftKey: true });
62
- expect(separator.getAttribute('aria-valuenow')).toBe('45');
63
- });
64
-
65
- it('clamps keyboard resizing to minSize/maxSize', () => {
66
- render(
67
- <ResizablePanelGroup direction="horizontal">
68
- <ResizablePanel defaultSize={50} minSize={45} maxSize={55}>
69
- <p>Left</p>
70
- </ResizablePanel>
71
- <ResizableHandle aria-label="Resize" />
72
- <ResizablePanel defaultSize={50} minSize={45} maxSize={55}>
73
- <p>Right</p>
74
- </ResizablePanel>
75
- </ResizablePanelGroup>,
76
- );
77
-
78
- const separator = screen.getByRole('separator', { name: 'Resize' });
79
- fireEvent.keyDown(separator, { key: 'ArrowRight', shiftKey: true });
80
- fireEvent.keyDown(separator, { key: 'ArrowRight', shiftKey: true });
81
- fireEvent.keyDown(separator, { key: 'ArrowRight', shiftKey: true });
82
- expect(separator.getAttribute('aria-valuenow')).toBe('55');
83
- });
84
-
85
- it('only affects the pair of panels adjacent to the handle that moved', () => {
86
- render(
87
- <ResizablePanelGroup direction="horizontal">
88
- <ResizablePanel defaultSize={34}>
89
- <p>A</p>
90
- </ResizablePanel>
91
- <ResizableHandle aria-label="Resize A-B" />
92
- <ResizablePanel defaultSize={33}>
93
- <p>B</p>
94
- </ResizablePanel>
95
- <ResizableHandle aria-label="Resize B-C" />
96
- <ResizablePanel defaultSize={33}>
97
- <p>C</p>
98
- </ResizablePanel>
99
- </ResizablePanelGroup>,
100
- );
101
-
102
- const first = screen.getByRole('separator', { name: 'Resize A-B' });
103
- const second = screen.getByRole('separator', { name: 'Resize B-C' });
104
- fireEvent.keyDown(first, { key: 'ArrowRight' });
105
- expect(second.getAttribute('aria-valuenow')).toBe('28');
106
- });
107
-
108
- it('uses ArrowDown/ArrowUp for vertical groups instead of ArrowRight/ArrowLeft', () => {
109
- render(
110
- <ResizablePanelGroup direction="vertical">
111
- <ResizablePanel defaultSize={50}>
112
- <p>Top</p>
113
- </ResizablePanel>
114
- <ResizableHandle aria-label="Resize" />
115
- <ResizablePanel defaultSize={50}>
116
- <p>Bottom</p>
117
- </ResizablePanel>
118
- </ResizablePanelGroup>,
119
- );
120
-
121
- const separator = screen.getByRole('separator', { name: 'Resize' });
122
- expect(separator.getAttribute('aria-orientation')).toBe('horizontal');
123
- fireEvent.keyDown(separator, { key: 'ArrowRight' });
124
- expect(separator.getAttribute('aria-valuenow')).toBe('50');
125
- fireEvent.keyDown(separator, { key: 'ArrowDown' });
126
- expect(separator.getAttribute('aria-valuenow')).toBe('55');
127
- });
128
- });
@@ -1,24 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import { useResponsiveLayout } from '../../hooks/useResponsiveLayout';
3
-
4
- export interface ResponsiveSurfaceProps {
5
- web: ReactNode;
6
- mobile: ReactNode;
7
- breakpointPx?: number;
8
- }
9
-
10
- /**
11
- * ResponsiveSurface — thin JSX convenience wrapper around
12
- * `useResponsiveLayout` for the common two-tree case: render an entirely
13
- * different component tree below the breakpoint, not a CSS squeeze of the
14
- * same one. Renders only whichever side is active — the other tree is never
15
- * mounted.
16
- *
17
- * This does not replace a plugin's own shell component (e.g. a
18
- * `MobileAwareShell` that also threads plugin-specific props like a refresh
19
- * signal) — those stay a thin per-plugin wrapper around this.
20
- */
21
- export function ResponsiveSurface({ web, mobile, breakpointPx }: ResponsiveSurfaceProps) {
22
- const { value } = useResponsiveLayout({ web, mobile, breakpointPx });
23
- return <>{value}</>;
24
- }
@@ -1,73 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { act, cleanup, render, screen } from '@testing-library/react';
4
- import { ResponsiveSurface } from '../ResponsiveSurface';
5
-
6
- let changeHandler: ((e: MediaQueryListEvent) => void) | null = null;
7
- let matches = false;
8
-
9
- function installMatchMedia() {
10
- changeHandler = null;
11
- vi.stubGlobal(
12
- 'matchMedia',
13
- vi.fn().mockImplementation((query: string) => ({
14
- matches,
15
- media: query,
16
- addEventListener: (_: string, cb: (e: MediaQueryListEvent) => void) => {
17
- changeHandler = cb;
18
- },
19
- removeEventListener: vi.fn(),
20
- addListener: vi.fn(),
21
- removeListener: vi.fn(),
22
- dispatchEvent: vi.fn(),
23
- })),
24
- );
25
- }
26
-
27
- describe('ResponsiveSurface', () => {
28
- beforeEach(() => {
29
- matches = false;
30
- installMatchMedia();
31
- });
32
- afterEach(() => {
33
- vi.unstubAllGlobals();
34
- cleanup();
35
- });
36
-
37
- it('renders the web tree by default and never mounts the mobile tree', () => {
38
- render(
39
- <ResponsiveSurface
40
- web={<div data-testid="web">web</div>}
41
- mobile={<div data-testid="mobile">mobile</div>}
42
- />,
43
- );
44
- expect(screen.getByTestId('web')).toBeDefined();
45
- expect(screen.queryByTestId('mobile')).toBeNull();
46
- });
47
-
48
- it('renders only the mobile tree below the breakpoint', () => {
49
- matches = true;
50
- installMatchMedia();
51
- render(
52
- <ResponsiveSurface
53
- web={<div data-testid="web">web</div>}
54
- mobile={<div data-testid="mobile">mobile</div>}
55
- />,
56
- );
57
- expect(screen.getByTestId('mobile')).toBeDefined();
58
- expect(screen.queryByTestId('web')).toBeNull();
59
- });
60
-
61
- it('swaps trees live when the viewport crosses the breakpoint', () => {
62
- render(
63
- <ResponsiveSurface
64
- web={<div data-testid="web">web</div>}
65
- mobile={<div data-testid="mobile">mobile</div>}
66
- />,
67
- );
68
- expect(screen.getByTestId('web')).toBeDefined();
69
- act(() => changeHandler?.({ matches: true } as MediaQueryListEvent));
70
- expect(screen.getByTestId('mobile')).toBeDefined();
71
- expect(screen.queryByTestId('web')).toBeNull();
72
- });
73
- });