@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,284 +0,0 @@
1
- 'use client';
2
-
3
- import { useCallback, useEffect, useRef, useState } from 'react';
4
- import type { RefObject } from 'react';
5
-
6
- export interface UseSnapCarouselOptions {
7
- /** Total number of slides — settle detection clamps to this range. */
8
- itemCount: number;
9
- /** Called when the user's scroll gesture settles on a different slide
10
- * index than the last one reported. */
11
- onSettle?: (index: number) => void;
12
- /** Debounce delay (ms) after the last `scroll` event before checking where
13
- * the container settled. Default 120 — matches the value this hook was
14
- * extracted from. Debounced rather than keyed to the `scrollend` event,
15
- * which pre-17.4 iOS Safari/WKWebView doesn't support. */
16
- debounceMs?: number;
17
- /** The index to seed `liveIndex` with before any scroll event has fired —
18
- * must match whatever the caller initially scrolls/renders to (typically
19
- * the same value used for `SwipableMobileCarousel`'s `activeIndex`).
20
- * Without this, `liveIndex` would start at 0 regardless of where the
21
- * carousel actually opens (e.g. a deep link straight to slide 8),
22
- * briefly unmounting every slide except the first few until the first
23
- * scroll event arrives to correct it. */
24
- initialIndex?: number;
25
- }
26
-
27
- export interface UseSnapCarouselResult {
28
- /** Attach to the `scroll-snap-type: x` scroll container. */
29
- scrollRef: RefObject<HTMLDivElement | null>;
30
- /** Imperatively scrolls the container to a slide index. */
31
- scrollToIndex: (index: number, behavior?: ScrollBehavior) => void;
32
- /** The slide index nearest the container's *current* scroll position,
33
- * updated synchronously on every `scroll` event — not debounced, and not
34
- * the same thing as the last-reported `onSettle` index. See its own
35
- * assignment below for why a consumer needs both. */
36
- liveIndex: number;
37
- }
38
-
39
- /**
40
- * useSnapCarousel — debounced "settled slide" detection over a native
41
- * `scroll-snap-type: x` container, extracted from `sovereign-tasks`'s
42
- * `MobileTasksCarousel` and independently reimplemented in
43
- * `sovereign-shopper`'s `MobileShopperCarousel` (RFC 0079, epic task 9.20).
44
- * Gives swipe-between-slides physics for free via native scroll-snap, with
45
- * this hook only handling "which slide did we land on."
46
- */
47
- export function useSnapCarousel({
48
- itemCount,
49
- onSettle,
50
- debounceMs = 120,
51
- initialIndex = 0,
52
- }: UseSnapCarouselOptions): UseSnapCarouselResult {
53
- const scrollRef = useRef<HTMLDivElement>(null);
54
- const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
55
- const lastIndexRef = useRef<number | null>(null);
56
- // Cleanup for scrollToIndex's scroll-snap-suspension workaround (see that
57
- // function's own comment) — lets an overlapping call cancel a still-
58
- // pending restore from an earlier one instead of two racing to re-enable
59
- // snap at the wrong time.
60
- const restoreSnapRef = useRef<(() => void) | null>(null);
61
- // Real-time (synchronous, not debounced) read of "which slide is the
62
- // container's scroll position nearest right now." A fast flick can carry
63
- // native scroll-snap momentum straight past an intermediate slide to one
64
- // two or more away in a single continuous gesture — the settle-detection
65
- // above deliberately still waits out the full debounce window before
66
- // reporting that via onSettle (so it can tell a real settle from drift,
67
- // see chainTrustedRef's own comment). But `SwipableMobileCarousel`'s mount
68
- // window is keyed off the *settled* index, so during that debounce window
69
- // the slide the container had already scrolled to — visually, right now —
70
- // was never in the mount window and had never been rendered at all: a
71
- // real, reproduced-on-video gap where the carousel shows nothing (not even
72
- // a loading skeleton) for the length of one full debounce cycle after a
73
- // multi-slide flick. `liveIndex` exists so the mount window can track
74
- // wherever the container currently visually is, independent of whether
75
- // that position has been confirmed as a real settle yet.
76
- const [liveIndex, setLiveIndex] = useState(initialIndex);
77
- // Kept in a ref so the scroll listener always calls the latest callback
78
- // without needing to be torn down and re-attached on every render.
79
- const onSettleRef = useRef(onSettle);
80
- onSettleRef.current = onSettle;
81
- // Timestamp (Date.now()) of the most recent real input (touch, wheel/
82
- // trackpad, or a mouse drag) — see the doc comment above `noteGesture`
83
- // below for why settle-detection is gated on this instead of firing for
84
- // any `scroll` event.
85
- const lastGestureAtRef = useRef(0);
86
- // Whether the *current* run of scroll events (since the last time the
87
- // container went quiet for debounceMs) was kicked off by real input. Set
88
- // at the start of each run by checking lastGestureAtRef, then held for the
89
- // whole run regardless of how long it continues — see `handleScroll`'s own
90
- // comment for why this can't just be "was there a gesture event within the
91
- // last debounceMs" re-checked at settle time: native momentum/snap-
92
- // correction after a real swipe can keep producing scroll events for
93
- // longer than any fixed slack window without a single further touch event,
94
- // and a first version of this fix that compared elapsed time against a
95
- // fixed `debounceMs * 2` slack dropped exactly those settles — silently
96
- // leaving activeIndex stuck on the old slide while the container had
97
- // already visually scrolled to the new one, which is worse than the bug
98
- // being fixed (the mount window then unmounts whatever's actually on
99
- // screen, since it's keyed off the now-stale index — a blank, un-
100
- // recoverable-without-reload carousel). `noteGesture` can also upgrade
101
- // trust mid-run, for a real gesture that starts while an untrusted run's
102
- // debounce timer is still pending.
103
- const chainTrustedRef = useRef(false);
104
-
105
- useEffect(() => {
106
- const el = scrollRef.current;
107
- if (!el) return;
108
- // A `scroll-snap-type: mandatory` container has no legitimate reason to
109
- // move on its own — every real position change is either (a) driven by
110
- // the finger/wheel/mouse still in contact, (b) the browser's own
111
- // momentum/snap-correction settling immediately after release, or (c)
112
- // our own scrollToIndex() call, which already updates lastIndexRef
113
- // synchronously so settle-detection for it is a no-op regardless. A
114
- // `scroll` event that arrives with none of the above recently active is
115
- // drift, not a settle — most commonly a slide's own content changing
116
- // size while it's still loading, which can nudge scrollLeft by a
117
- // fraction of a slide width. Previously any such event that happened to
118
- // round to a different index than the currently active one was treated
119
- // as a genuine settle, silently "auto-swiping" the carousel back to
120
- // whatever slide that rounding landed on — reproduced live via a user
121
- // screen recording (swiping forward to a still-loading slide, then the
122
- // carousel snapping back to the previous one ~150ms later with no
123
- // further touch input) and confirmed via a unit test showing a second,
124
- // unrelated `scroll` event alone was enough to trigger a second,
125
- // contradicting `onSettle` call.
126
- function noteGesture() {
127
- lastGestureAtRef.current = Date.now();
128
- // Upgrades the currently in-flight run too, not just the next one —
129
- // covers a real gesture starting while an untrusted run's debounce
130
- // timer (started by an earlier, unrelated drift scroll event) is
131
- // still pending.
132
- chainTrustedRef.current = true;
133
- }
134
- function handlePointerMove(event: PointerEvent) {
135
- // Ignore hover — only a held button (mouse drag) counts as input.
136
- if (event.buttons) noteGesture();
137
- }
138
- function updateLiveIndexNow() {
139
- const current = scrollRef.current;
140
- if (!current) return;
141
- const width = current.clientWidth;
142
- if (!width) return;
143
- const idx = Math.max(0, Math.min(itemCount - 1, Math.round(current.scrollLeft / width)));
144
- // Bails out (same reference, no re-render) when the index hasn't
145
- // actually changed — a scroll container fires many `scroll` events
146
- // while passing through the same slide's territory, not just at its
147
- // boundaries. Synchronous rather than rAF-throttled: jsdom (this
148
- // hook's own test environment) doesn't reliably run
149
- // requestAnimationFrame callbacks under fake timers, and browsers
150
- // already coalesce native scroll events to roughly once per frame on
151
- // their own, so a second throttle here bought nothing but test
152
- // fragility.
153
- setLiveIndex((prev) => (prev === idx ? prev : idx));
154
- }
155
- function handleScroll() {
156
- updateLiveIndexNow();
157
- if (timerRef.current) {
158
- clearTimeout(timerRef.current);
159
- } else {
160
- // No debounce timer pending means the container had been fully
161
- // quiet — this scroll event starts a new run. Trust it only if real
162
- // input happened recently; once granted, trust holds for the whole
163
- // run (see chainTrustedRef's own doc comment above) no matter how
164
- // long momentum/snap-correction keeps producing scroll events after
165
- // this point with no further input.
166
- chainTrustedRef.current = Date.now() - lastGestureAtRef.current <= debounceMs;
167
- }
168
- timerRef.current = setTimeout(() => {
169
- timerRef.current = null;
170
- const trusted = chainTrustedRef.current;
171
- chainTrustedRef.current = false;
172
- if (!trusted) return;
173
- const current = scrollRef.current;
174
- if (!current) return;
175
- const width = current.clientWidth;
176
- if (!width) return;
177
- const rawIndex = Math.round(current.scrollLeft / width);
178
- const newIndex = Math.max(0, Math.min(itemCount - 1, rawIndex));
179
- if (newIndex === lastIndexRef.current) return;
180
- lastIndexRef.current = newIndex;
181
- onSettleRef.current?.(newIndex);
182
- }, debounceMs);
183
- }
184
- el.addEventListener('scroll', handleScroll, { passive: true });
185
- el.addEventListener('touchstart', noteGesture, { passive: true });
186
- el.addEventListener('touchmove', noteGesture, { passive: true });
187
- el.addEventListener('wheel', noteGesture, { passive: true });
188
- el.addEventListener('pointerdown', noteGesture);
189
- el.addEventListener('pointermove', handlePointerMove);
190
- return () => {
191
- el.removeEventListener('scroll', handleScroll);
192
- el.removeEventListener('touchstart', noteGesture);
193
- el.removeEventListener('touchmove', noteGesture);
194
- el.removeEventListener('wheel', noteGesture);
195
- el.removeEventListener('pointerdown', noteGesture);
196
- el.removeEventListener('pointermove', handlePointerMove);
197
- if (timerRef.current) clearTimeout(timerRef.current);
198
- };
199
- }, [itemCount, debounceMs]);
200
-
201
- // Memoized so its reference stays stable across renders — SwipableMobile
202
- // Carousel depends on it in a useEffect deps array alongside
203
- // clampedActiveIndex, and an unmemoized function recreated on every
204
- // render (e.g. every time liveIndex itself changes below) would make that
205
- // effect re-fire on every scroll, calling scrollToIndex again and — since
206
- // it also resets liveIndex to whatever index it was told to scroll to —
207
- // immediately stomping the very liveIndex update that triggered the
208
- // re-render in the first place. Caught by this hook's own test suite
209
- // (a live-index test that failed until this was memoized), not just
210
- // reasoned about — worth keeping as a regression guard, not just a
211
- // performance nicety.
212
- const scrollToIndex = useCallback((index: number, behavior: ScrollBehavior = 'smooth') => {
213
- const el = scrollRef.current;
214
- if (!el) return;
215
- lastIndexRef.current = index;
216
- // Belt-and-suspenders: a real scrollTo() also fires its own 'scroll'
217
- // event, which updates liveIndex synchronously too — but jsdom's mocked
218
- // scrollTo (this hook's own test environment) doesn't, and the initial
219
- // mount scroll / reorder-jump fix both need the target slide mounted
220
- // immediately regardless.
221
- setLiveIndex(index);
222
-
223
- // Cancel any still-pending restore from an earlier smooth scroll before
224
- // starting this one, so they don't race to re-enable snap at the wrong
225
- // time (e.g. a dot-jump fired while a previous jump's restore timer is
226
- // still pending).
227
- if (restoreSnapRef.current) {
228
- restoreSnapRef.current();
229
- restoreSnapRef.current = null;
230
- }
231
-
232
- const target = index * el.clientWidth;
233
-
234
- if (behavior === 'smooth') {
235
- // A programmatic `scrollTo({ behavior: 'smooth' })` on this element
236
- // can silently do nothing at all — not a jank/timing issue, the
237
- // container just never moves, with no error and no scroll events.
238
- // Reproduced live via the design system's own footer/dot-jump
239
- // navigation in sovereign-tasks (routes external activeIndex changes
240
- // through this exact path): the identical call with
241
- // `behavior: 'instant'` moved the container immediately, `'smooth'`
242
- // did nothing — reproduced both with `scroll-snap-type: mandatory` in
243
- // place *and*, isolating further, on a plain scroll-snap-free element
244
- // in the same environment, so `scroll-snap-type` alone doesn't fully
245
- // explain it. Two independent mitigations, since the exact trigger
246
- // isn't nailed down: (1) suspend snap for the duration of the
247
- // animated scroll on the chance it *is* a snap/animation conflict in
248
- // some engines; (2) below, a correctness-net instant scrollTo if the
249
- // container still isn't at the target once the animation should have
250
- // finished — cheap and idempotent when the smooth scroll *did* work
251
- // (already at the target, the check is a no-op), and the difference
252
- // between a graceful animation and an abrupt correction if it didn't,
253
- // rather than a carousel that silently desyncs forever with nothing
254
- // to ever correct it.
255
- // Narrowed, stable binding for the closures below — TS can't carry
256
- // the `if (!el) return` narrowing of the outer `el` into a nested
257
- // function declaration.
258
- const scrollEl = el;
259
- const prevSnapType = scrollEl.style.scrollSnapType;
260
- scrollEl.style.scrollSnapType = 'none';
261
- let settled = false;
262
- // Matches typical browser smooth-scroll duration; also the fallback
263
- // for engines with no `scrollend` (pre-17.4 iOS Safari/WKWebView).
264
- const timeoutId = setTimeout(finish, 500);
265
- function finish() {
266
- if (settled) return;
267
- settled = true;
268
- clearTimeout(timeoutId);
269
- scrollEl.removeEventListener('scrollend', finish);
270
- scrollEl.style.scrollSnapType = prevSnapType;
271
- restoreSnapRef.current = null;
272
- if (Math.abs(scrollEl.scrollLeft - target) > 1) {
273
- scrollEl.scrollTo({ left: target, behavior: 'instant' });
274
- }
275
- }
276
- scrollEl.addEventListener('scrollend', finish, { once: true });
277
- restoreSnapRef.current = finish;
278
- }
279
-
280
- el.scrollTo({ left: target, behavior });
281
- }, []);
282
-
283
- return { scrollRef, scrollToIndex, liveIndex };
284
- }
@@ -1,107 +0,0 @@
1
- 'use client';
2
-
3
- import { useRef } from 'react';
4
- import type { PointerEvent as ReactPointerEvent, RefObject } from 'react';
5
-
6
- export interface UseSwipeRevealOptions {
7
- /** Max reveal distance in px — the row translates by `-revealWidth` when open. */
8
- revealWidth: number;
9
- /** Whether the reveal is currently open. Controlled by the caller so a
10
- * list of rows can coordinate "only one open at a time" — this hook has
11
- * no open state of its own. */
12
- open: boolean;
13
- /** Called when a drag releases past the halfway point — the caller should
14
- * set `open` to true. */
15
- onOpen: () => void;
16
- /** Called when a drag releases before the halfway point — the caller
17
- * should set `open` to false. */
18
- onClose: () => void;
19
- /** Skip entirely (hooks can't be called conditionally). */
20
- disabled?: boolean;
21
- }
22
-
23
- export interface UseSwipeRevealHandlers {
24
- onPointerDown: (e: ReactPointerEvent) => void;
25
- onPointerMove: (e: ReactPointerEvent) => void;
26
- onPointerUp: (e: ReactPointerEvent) => void;
27
- onPointerCancel: (e: ReactPointerEvent) => void;
28
- }
29
-
30
- export interface UseSwipeRevealResult {
31
- /** Attach to the swipeable row element — the hook writes a live transform
32
- * to it directly during the drag (not via React state) so the row tracks
33
- * the finger at 60fps with no re-render per pointermove. */
34
- rowRef: RefObject<HTMLDivElement | null>;
35
- /** Spread onto the row's pointer event handlers. */
36
- handlers: UseSwipeRevealHandlers;
37
- }
38
-
39
- /**
40
- * useSwipeReveal — horizontal swipe-to-reveal (e.g. Done/Delete actions
41
- * behind a list row), extracted from `sovereign-tasks`'s `TaskItem`/
42
- * `ListSidebar`, which independently hand-rolled the identical gesture twice
43
- * with only `revealWidth` differing (RFC 0079, epic task 9.20).
44
- *
45
- * Axis-locks on the first 8px of movement (so a vertical scroll or the
46
- * carousel's own horizontal swipe-between-slides gesture isn't hijacked by a
47
- * diagonal drag) and only resolves to open/closed on release, past the
48
- * halfway point of `revealWidth`.
49
- */
50
- export function useSwipeReveal({
51
- revealWidth,
52
- open,
53
- onOpen,
54
- onClose,
55
- disabled = false,
56
- }: UseSwipeRevealOptions): UseSwipeRevealResult {
57
- const rowRef = useRef<HTMLDivElement>(null);
58
- const dragState = useRef<{
59
- startX: number;
60
- startY: number;
61
- locked: 'horizontal' | 'vertical' | null;
62
- } | null>(null);
63
-
64
- function onPointerDown(e: ReactPointerEvent) {
65
- if (disabled) return;
66
- e.currentTarget.setPointerCapture(e.pointerId);
67
- dragState.current = { startX: e.clientX, startY: e.clientY, locked: null };
68
- }
69
-
70
- function onPointerMove(e: ReactPointerEvent) {
71
- const state = dragState.current;
72
- if (!state) return;
73
- const dx = e.clientX - state.startX;
74
- const dy = e.clientY - state.startY;
75
- if (!state.locked) {
76
- if (Math.abs(dx) < 8 && Math.abs(dy) < 8) return;
77
- state.locked = Math.abs(dx) > Math.abs(dy) ? 'horizontal' : 'vertical';
78
- }
79
- if (state.locked !== 'horizontal') return;
80
- e.preventDefault();
81
- const base = open ? -revealWidth : 0;
82
- const next = Math.min(0, Math.max(-revealWidth, base + dx));
83
- if (rowRef.current) rowRef.current.style.transform = `translateX(${next}px)`;
84
- }
85
-
86
- function releaseDrag(e: ReactPointerEvent) {
87
- const state = dragState.current;
88
- dragState.current = null;
89
- if (!state || state.locked !== 'horizontal') return;
90
- const dx = e.clientX - state.startX;
91
- const base = open ? -revealWidth : 0;
92
- const finalX = Math.min(0, Math.max(-revealWidth, base + dx));
93
- if (rowRef.current) rowRef.current.style.transform = '';
94
- if (finalX < -revealWidth / 2) onOpen();
95
- else onClose();
96
- }
97
-
98
- return {
99
- rowRef,
100
- handlers: {
101
- onPointerDown,
102
- onPointerMove,
103
- onPointerUp: releaseDrag,
104
- onPointerCancel: releaseDrag,
105
- },
106
- };
107
- }
@@ -1,235 +0,0 @@
1
- 'use client';
2
-
3
- import { useRef } from 'react';
4
- import type { PointerEvent as ReactPointerEvent, RefObject } from 'react';
5
-
6
- export type SwipeDirection = 'left' | 'right' | 'up' | 'down';
7
-
8
- /** Minimum effective drag distance (px) before a direction is read at all —
9
- * keeps a tap or a tiny jitter from registering as a swipe. Matches
10
- * useSwipeReveal's own deadzone. */
11
- const DEADZONE_PX = 8;
12
-
13
- /** Horizontal drag distance (px) that reaches the full tilt cap. */
14
- const ROTATION_RANGE_PX = 240;
15
- const ROTATION_MAX_DEG = 12;
16
-
17
- /** Duration (ms) of both the commit fling-out and the spring-back-under-
18
- * threshold transition. Exported so SwipeStack can hold a just-committed
19
- * card in place for exactly this long before advancing to the next one. */
20
- export const SWIPE_STACK_TRANSITION_MS = 220;
21
-
22
- const ALL_DIRECTIONS: readonly SwipeDirection[] = ['left', 'right', 'up', 'down'];
23
-
24
- /** Unit vector per direction — reused for both the fling-out offset and the
25
- * tilt sign (horizontal directions tilt, vertical ones don't: x is ±1/0). */
26
- const UNIT_VECTOR: Record<SwipeDirection, readonly [number, number]> = {
27
- left: [-1, 0],
28
- right: [1, 0],
29
- up: [0, -1],
30
- down: [0, 1],
31
- };
32
-
33
- export interface UseSwipeStackOptions {
34
- /** Directions this drag can move toward and resolve to. A direction left
35
- * out of this list is a wall, not just an unreachable outcome — the card
36
- * will not visually move that way at all (see clampToLiveDirections). */
37
- directions: readonly SwipeDirection[];
38
- /** Effective distance (px) a drag must cross before release commits to
39
- * that direction instead of springing back. No velocity component — a
40
- * fast short flick under this distance still springs back. */
41
- threshold?: number;
42
- /** Fires once, synchronously, when a drag (or triggerCommit) resolves to
43
- * a live direction past threshold. This hook has already started the
44
- * fling-out animation on cardRef's element by the time this is called —
45
- * the caller only needs to react to the outcome, not drive the motion. */
46
- onCommit: (direction: SwipeDirection) => void;
47
- /** Disables both the drag and triggerCommit — e.g. while there is no
48
- * current card to act on. */
49
- disabled?: boolean;
50
- }
51
-
52
- export interface UseSwipeStackHandlers {
53
- onPointerDown: (e: ReactPointerEvent) => void;
54
- onPointerMove: (e: ReactPointerEvent) => void;
55
- onPointerUp: (e: ReactPointerEvent) => void;
56
- onPointerCancel: (e: ReactPointerEvent) => void;
57
- }
58
-
59
- export interface UseSwipeStackResult {
60
- /** Attach to the card element that should translate/rotate with the drag. */
61
- cardRef: RefObject<HTMLDivElement | null>;
62
- /** Attach to the ancestor of both the card and any direction-stamp
63
- * overlays. The hook writes live drag progress here as CSS custom
64
- * properties (--sv-stack-progress-left/right/up/down, each 0–1) so
65
- * stamps — siblings of the card, not the card itself — can react without
66
- * a re-render per pointermove. */
67
- wrapRef: RefObject<HTMLDivElement | null>;
68
- handlers: UseSwipeStackHandlers;
69
- /** CSS touch-action for the card, derived from which directions are live
70
- * — an axis with nothing configured on it stays native (pan-x/pan-y) so
71
- * a page can still scroll through a stack that only uses the other axis;
72
- * `none` only once both axes are actually needed. */
73
- touchAction: string;
74
- /** Programmatically commits a direction — the same fling animation and
75
- * onCommit call a real drag past threshold would produce. Backs the
76
- * non-gesture fallback buttons: they are not a separate code path, just
77
- * a different way to call this. No-ops if the direction isn't live or
78
- * the hook is disabled. */
79
- triggerCommit: (direction: SwipeDirection) => void;
80
- }
81
-
82
- function clamp(value: number, min: number, max: number): number {
83
- return Math.min(max, Math.max(min, value));
84
- }
85
-
86
- /** Zeroes out movement toward any direction not in `live` — the card
87
- * behaves as if a wall exists there instead of just being an unreachable
88
- * commit outcome, so e.g. a left/right-only stack never visually drifts
89
- * vertically. */
90
- function clampToLiveDirections(
91
- dx: number,
92
- dy: number,
93
- live: ReadonlySet<SwipeDirection>,
94
- ): [number, number] {
95
- const x = dx > 0 ? (live.has('right') ? dx : 0) : live.has('left') ? dx : 0;
96
- const y = dy > 0 ? (live.has('down') ? dy : 0) : live.has('up') ? dy : 0;
97
- return [x, y];
98
- }
99
-
100
- function resolveDirection(
101
- dx: number,
102
- dy: number,
103
- live: ReadonlySet<SwipeDirection>,
104
- ): SwipeDirection | null {
105
- const absX = Math.abs(dx);
106
- const absY = Math.abs(dy);
107
- if (absX < DEADZONE_PX && absY < DEADZONE_PX) return null;
108
- const candidate: SwipeDirection =
109
- absX > absY ? (dx > 0 ? 'right' : 'left') : dy > 0 ? 'down' : 'up';
110
- return live.has(candidate) ? candidate : null;
111
- }
112
-
113
- /**
114
- * useSwipeStack — hand-rolled 4-directional free drag, extending
115
- * useSwipeReveal's pattern (raw Pointer Events, a deadzone, transform
116
- * written straight to a ref, resolved only on release) from one axis with
117
- * two outcomes to four directions with a tilt. Threshold-only on purpose,
118
- * matching useSwipeReveal — no velocity tracking, so a fast short flick
119
- * under `threshold` still springs back.
120
- */
121
- export function useSwipeStack({
122
- directions,
123
- threshold = 96,
124
- onCommit,
125
- disabled = false,
126
- }: UseSwipeStackOptions): UseSwipeStackResult {
127
- const cardRef = useRef<HTMLDivElement>(null);
128
- const wrapRef = useRef<HTMLDivElement>(null);
129
- const dragState = useRef<{ startX: number; startY: number } | null>(null);
130
- const live = new Set(directions);
131
-
132
- function writeProgress(direction: SwipeDirection | null, progress: number) {
133
- const wrap = wrapRef.current;
134
- if (!wrap) return;
135
- for (const d of ALL_DIRECTIONS) {
136
- wrap.style.setProperty(`--sv-stack-progress-${d}`, d === direction ? String(progress) : '0');
137
- }
138
- }
139
-
140
- function writeTransform(dx: number, dy: number) {
141
- const card = cardRef.current;
142
- if (!card) return;
143
- const rotation = clamp(
144
- (dx / ROTATION_RANGE_PX) * ROTATION_MAX_DEG,
145
- -ROTATION_MAX_DEG,
146
- ROTATION_MAX_DEG,
147
- );
148
- card.style.transform = `translate(${dx}px, ${dy}px) rotate(${rotation}deg)`;
149
- }
150
-
151
- function springBack() {
152
- const card = cardRef.current;
153
- if (!card) return;
154
- card.style.transition = `transform ${SWIPE_STACK_TRANSITION_MS}ms ease`;
155
- card.style.transform = '';
156
- }
157
-
158
- function flingOut(direction: SwipeDirection) {
159
- const card = cardRef.current;
160
- if (!card) return;
161
- const distance = 1.4 * Math.max(window.innerWidth, window.innerHeight);
162
- const [ux, uy] = UNIT_VECTOR[direction];
163
- card.style.transition = `transform ${SWIPE_STACK_TRANSITION_MS}ms ease`;
164
- card.style.transform = `translate(${ux * distance}px, ${uy * distance}px) rotate(${ux * ROTATION_MAX_DEG}deg)`;
165
- }
166
-
167
- function onPointerDown(e: ReactPointerEvent) {
168
- if (disabled) return;
169
- e.currentTarget.setPointerCapture(e.pointerId);
170
- dragState.current = { startX: e.clientX, startY: e.clientY };
171
- if (cardRef.current) cardRef.current.style.transition = '';
172
- }
173
-
174
- function onPointerMove(e: ReactPointerEvent) {
175
- const state = dragState.current;
176
- if (!state) return;
177
- const [dx, dy] = clampToLiveDirections(
178
- e.clientX - state.startX,
179
- e.clientY - state.startY,
180
- live,
181
- );
182
- writeTransform(dx, dy);
183
- const direction = resolveDirection(dx, dy, live);
184
- if (direction) e.preventDefault();
185
- writeProgress(
186
- direction,
187
- direction ? clamp(Math.max(Math.abs(dx), Math.abs(dy)) / threshold, 0, 1) : 0,
188
- );
189
- }
190
-
191
- function release(e: ReactPointerEvent) {
192
- const state = dragState.current;
193
- dragState.current = null;
194
- if (!state) return;
195
- const [dx, dy] = clampToLiveDirections(
196
- e.clientX - state.startX,
197
- e.clientY - state.startY,
198
- live,
199
- );
200
- const direction = resolveDirection(dx, dy, live);
201
- writeProgress(null, 0);
202
- const distance = Math.max(Math.abs(dx), Math.abs(dy));
203
- if (direction && distance >= threshold) {
204
- flingOut(direction);
205
- onCommit(direction);
206
- } else {
207
- springBack();
208
- }
209
- }
210
-
211
- function triggerCommit(direction: SwipeDirection) {
212
- if (disabled || !live.has(direction)) return;
213
- flingOut(direction);
214
- onCommit(direction);
215
- }
216
-
217
- const hasHorizontal = live.has('left') || live.has('right');
218
- const hasVertical = live.has('up') || live.has('down');
219
- const touchAction =
220
- hasHorizontal && hasVertical
221
- ? 'none'
222
- : hasHorizontal
223
- ? 'pan-y'
224
- : hasVertical
225
- ? 'pan-x'
226
- : 'auto';
227
-
228
- return {
229
- cardRef,
230
- wrapRef,
231
- handlers: { onPointerDown, onPointerMove, onPointerUp: release, onPointerCancel: release },
232
- touchAction,
233
- triggerCommit,
234
- };
235
- }