@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,925 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { Card } from '../components/Card/Card';
4
- import {
5
- useCarouselRouteSync,
6
- useCommitOnEnterOrBlur,
7
- useDoubleTapHandler,
8
- useIsMobile,
9
- useIsOffline,
10
- useLongPress,
11
- useOfflineTileState,
12
- useResponsiveLayout,
13
- useSingleOrDoubleTap,
14
- useSnapCarousel,
15
- useSwipeReveal,
16
- } from '../hooks';
17
-
18
- // ---------------------------------------------------------------------------
19
- // Shared primitives (mirrors MobilePatterns.stories.tsx's doc styling)
20
- // ---------------------------------------------------------------------------
21
-
22
- const ff = 'var(--sv-font-family)';
23
-
24
- function Heading({ level = 2, children }: { level?: 1 | 2 | 3; children: React.ReactNode }) {
25
- const sizes: Record<number, string> = { 1: '1.75rem', 2: '1.125rem', 3: '0.9375rem' };
26
- const weights: Record<number, number> = { 1: 700, 2: 600, 3: 600 };
27
- const Tag = `h${level}` as 'h1' | 'h2' | 'h3';
28
- return (
29
- <Tag
30
- style={{
31
- fontFamily: ff,
32
- fontSize: sizes[level],
33
- fontWeight: weights[level],
34
- color: 'var(--sv-color-text-primary)',
35
- margin: 0,
36
- lineHeight: 1.3,
37
- }}
38
- >
39
- {children}
40
- </Tag>
41
- );
42
- }
43
-
44
- function Body({ children }: { children: React.ReactNode }) {
45
- return (
46
- <p
47
- style={{
48
- fontFamily: ff,
49
- fontSize: 'var(--sv-font-size-sm)',
50
- color: 'var(--sv-color-text-muted)',
51
- margin: '0.5rem 0 0',
52
- lineHeight: 1.6,
53
- }}
54
- >
55
- {children}
56
- </p>
57
- );
58
- }
59
-
60
- function SectionHeader({ title, subtitle }: { title: string; subtitle?: string }) {
61
- return (
62
- <div
63
- style={{
64
- paddingBottom: 'var(--sv-space-3)',
65
- borderBottom: '2px solid var(--sv-color-accent)',
66
- marginBottom: 'var(--sv-space-5)',
67
- }}
68
- >
69
- <Heading level={2}>{title}</Heading>
70
- {subtitle && <Body>{subtitle}</Body>}
71
- </div>
72
- );
73
- }
74
-
75
- function Callout({
76
- type = 'info',
77
- children,
78
- }: {
79
- type?: 'info' | 'warn' | 'tip';
80
- children: React.ReactNode;
81
- }) {
82
- const map = {
83
- info: {
84
- bg: 'var(--sv-color-info-surface)',
85
- border: 'var(--sv-color-info-border)',
86
- text: 'var(--sv-color-info-text)',
87
- label: 'ℹ',
88
- },
89
- warn: {
90
- bg: 'var(--sv-color-warning-surface)',
91
- border: 'var(--sv-color-warning-border)',
92
- text: 'var(--sv-color-warning-text)',
93
- label: '⚠',
94
- },
95
- tip: {
96
- bg: 'var(--sv-color-success-surface)',
97
- border: 'var(--sv-color-success-border)',
98
- text: 'var(--sv-color-success-text)',
99
- label: '✓',
100
- },
101
- };
102
- const c = map[type];
103
- return (
104
- <div
105
- style={{
106
- background: c.bg,
107
- border: `1px solid ${c.border}`,
108
- borderRadius: 'var(--sv-radius-md)',
109
- padding: 'var(--sv-space-3) var(--sv-space-4)',
110
- display: 'flex',
111
- gap: 'var(--sv-space-2)',
112
- alignItems: 'flex-start',
113
- marginBottom: 'var(--sv-space-4)',
114
- }}
115
- >
116
- <span style={{ color: c.text, fontWeight: 700, flexShrink: 0, fontSize: '0.875rem' }}>
117
- {c.label}
118
- </span>
119
- <p
120
- style={{
121
- fontFamily: ff,
122
- fontSize: 'var(--sv-font-size-sm)',
123
- color: c.text,
124
- margin: 0,
125
- lineHeight: 1.55,
126
- }}
127
- >
128
- {children}
129
- </p>
130
- </div>
131
- );
132
- }
133
-
134
- function CodeBlock({ children }: { children: string }) {
135
- return (
136
- <pre
137
- style={{
138
- fontFamily: 'var(--sv-font-family-mono)',
139
- fontSize: '0.75rem',
140
- background: 'var(--sv-color-surface-sunken)',
141
- border: '1px solid var(--sv-color-border)',
142
- borderRadius: 'var(--sv-radius-md)',
143
- padding: 'var(--sv-space-3) var(--sv-space-4)',
144
- marginTop: 'var(--sv-space-3)',
145
- overflowX: 'auto',
146
- color: 'var(--sv-color-text-primary)',
147
- lineHeight: 1.6,
148
- }}
149
- >
150
- {children}
151
- </pre>
152
- );
153
- }
154
-
155
- function EventLog({ events }: { events: string[] }) {
156
- return (
157
- <div
158
- style={{
159
- marginTop: 'var(--sv-space-3)',
160
- fontFamily: 'var(--sv-font-family-mono)',
161
- fontSize: '0.75rem',
162
- color: 'var(--sv-color-text-muted)',
163
- background: 'var(--sv-color-surface-sunken)',
164
- border: '1px solid var(--sv-color-border)',
165
- borderRadius: 'var(--sv-radius-md)',
166
- padding: 'var(--sv-space-2) var(--sv-space-3)',
167
- minHeight: '2.5em',
168
- }}
169
- >
170
- {events.length === 0 ? '(no events yet)' : events.slice(-5).join('\n')}
171
- </div>
172
- );
173
- }
174
-
175
- // ---------------------------------------------------------------------------
176
- // Interactive demos
177
- // ---------------------------------------------------------------------------
178
-
179
- function LongPressDemo() {
180
- const [events, setEvents] = useState<string[]>([]);
181
- const log = (msg: string) =>
182
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
183
- const longPress = useLongPress({ onLongPress: () => log('onLongPress fired') });
184
-
185
- return (
186
- <div>
187
- <div
188
- {...longPress}
189
- style={{
190
- ...longPress.style,
191
- padding: 'var(--sv-space-5)',
192
- borderRadius: 'var(--sv-radius-md)',
193
- border: '1px dashed var(--sv-color-border-strong)',
194
- background: 'var(--sv-color-surface)',
195
- textAlign: 'center',
196
- fontFamily: ff,
197
- fontSize: 'var(--sv-font-size-sm)',
198
- color: 'var(--sv-color-text-muted)',
199
- cursor: 'default',
200
- }}
201
- >
202
- Touch and hold (real touch input only — see note below)
203
- </div>
204
- <EventLog events={events} />
205
- <Callout type="info">
206
- The hook only arms for <code>pointerType === &apos;touch&apos;</code> — a desktop mouse
207
- click never starts the timer, so mouse text-selection is never disabled. Test this on a real
208
- touch device or with devtools&apos; device toolbar (which synthesizes real touch pointer
209
- events), not a plain mouse click in this preview.
210
- </Callout>
211
- </div>
212
- );
213
- }
214
-
215
- function DoubleTapDemo() {
216
- const [events, setEvents] = useState<string[]>([]);
217
- const log = (msg: string) =>
218
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
219
-
220
- const handleSwatchTap = useDoubleTapHandler<React.MouseEvent>(() => log('double-tap: swatch'));
221
- const handleTitleTap = useSingleOrDoubleTap<React.MouseEvent>(
222
- () => log('single tap: would navigate'),
223
- () => log('double-tap: would rename'),
224
- );
225
-
226
- return (
227
- <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--sv-space-3)' }}>
228
- <div style={{ display: 'flex', gap: 'var(--sv-space-3)', alignItems: 'center' }}>
229
- <button
230
- type="button"
231
- onClick={handleSwatchTap}
232
- style={{
233
- width: 40,
234
- height: 40,
235
- borderRadius: 'var(--sv-radius-full)',
236
- background: 'var(--sv-color-accent)',
237
- border: 'none',
238
- cursor: 'pointer',
239
- }}
240
- aria-label="Double-tap demo swatch"
241
- />
242
- <span
243
- style={{
244
- fontFamily: ff,
245
- fontSize: 'var(--sv-font-size-sm)',
246
- color: 'var(--sv-color-text-muted)',
247
- }}
248
- >
249
- useDoubleTapHandler — nothing to preempt, double-click/double-tap fires immediately
250
- </span>
251
- </div>
252
- <div style={{ display: 'flex', gap: 'var(--sv-space-3)', alignItems: 'center' }}>
253
- <button
254
- type="button"
255
- onClick={handleTitleTap}
256
- style={{
257
- padding: 'var(--sv-space-2) var(--sv-space-4)',
258
- borderRadius: 'var(--sv-radius-md)',
259
- background: 'var(--sv-color-surface-sunken)',
260
- border: '1px solid var(--sv-color-border)',
261
- fontFamily: ff,
262
- fontSize: 'var(--sv-font-size-sm)',
263
- cursor: 'pointer',
264
- }}
265
- >
266
- List title
267
- </button>
268
- <span
269
- style={{
270
- fontFamily: ff,
271
- fontSize: 'var(--sv-font-size-sm)',
272
- color: 'var(--sv-color-text-muted)',
273
- }}
274
- >
275
- useSingleOrDoubleTap — single tap deferred ~350ms so a double can preempt it
276
- </span>
277
- </div>
278
- <EventLog events={events} />
279
- </div>
280
- );
281
- }
282
-
283
- function CommitOnEnterOrBlurDemo() {
284
- const [value, setValue] = useState('');
285
- const [events, setEvents] = useState<string[]>([]);
286
- const log = (msg: string) =>
287
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
288
- const commitHandlers = useCommitOnEnterOrBlur(() => log(`commit: "${value}"`));
289
-
290
- return (
291
- <div>
292
- <input
293
- value={value}
294
- onChange={(e) => setValue(e.target.value)}
295
- {...commitHandlers}
296
- placeholder="Type, then press Enter or click away…"
297
- style={{
298
- width: '100%',
299
- boxSizing: 'border-box',
300
- padding: 'var(--sv-space-2) var(--sv-space-3)',
301
- borderRadius: 'var(--sv-radius-md)',
302
- border: '1px solid var(--sv-color-border-strong)',
303
- background: 'var(--sv-color-surface)',
304
- color: 'var(--sv-color-text-primary)',
305
- fontFamily: ff,
306
- fontSize: 'var(--sv-font-size-sm)',
307
- }}
308
- />
309
- <EventLog events={events} />
310
- <Callout type="info">
311
- Tries to reproduce the bug this hook fixes: on iOS, tap into the field, type something, then
312
- dismiss the keyboard via the native Done/checkmark toolbar instead of the Return key — both
313
- now log a commit here, where an Enter-only handler would silently drop the checkmark path.
314
- </Callout>
315
- </div>
316
- );
317
- }
318
-
319
- function IsMobileDemo() {
320
- const isMobile = useIsMobile();
321
- return (
322
- <div
323
- style={{
324
- padding: 'var(--sv-space-4)',
325
- borderRadius: 'var(--sv-radius-md)',
326
- background: isMobile ? 'var(--sv-color-success-surface)' : 'var(--sv-color-info-surface)',
327
- color: isMobile ? 'var(--sv-color-success-text)' : 'var(--sv-color-info-text)',
328
- fontFamily: ff,
329
- fontSize: 'var(--sv-font-size-sm)',
330
- fontWeight: 600,
331
- textAlign: 'center',
332
- }}
333
- >
334
- useIsMobile() → {String(isMobile)} — resize the preview or switch the viewport toolbar to see
335
- this flip at 768px.
336
- </div>
337
- );
338
- }
339
-
340
- function IsOfflineDemo() {
341
- const isOffline = useIsOffline();
342
- return (
343
- <div
344
- style={{
345
- padding: 'var(--sv-space-4)',
346
- borderRadius: 'var(--sv-radius-md)',
347
- background: isOffline
348
- ? 'var(--sv-color-warning-surface)'
349
- : 'var(--sv-color-success-surface)',
350
- color: isOffline ? 'var(--sv-color-warning-text)' : 'var(--sv-color-success-text)',
351
- fontFamily: ff,
352
- fontSize: 'var(--sv-font-size-sm)',
353
- fontWeight: 600,
354
- textAlign: 'center',
355
- }}
356
- >
357
- useIsOffline() → {String(isOffline)} — toggle DevTools &gt; Network &gt; Offline (or your OS's
358
- airplane mode) to see this flip.
359
- </div>
360
- );
361
- }
362
-
363
- function OfflineTileStateDemo() {
364
- const [tier, setTier] = useState<'none' | 'offline-first' | 'device-only'>('device-only');
365
- const [deviceOnlyAvailable, setDeviceOnlyAvailable] = useState(false);
366
- const state = useOfflineTileState(tier === 'none' ? undefined : tier, deviceOnlyAvailable);
367
-
368
- return (
369
- <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--sv-space-3)' }}>
370
- <div
371
- style={{ display: 'flex', gap: 'var(--sv-space-4)', alignItems: 'center', fontFamily: ff }}
372
- >
373
- <label style={{ fontSize: 'var(--sv-font-size-sm)' }}>
374
- offline tier:{' '}
375
- <select value={tier} onChange={(e) => setTier(e.target.value as typeof tier)}>
376
- <option value="none">(none)</option>
377
- <option value="offline-first">offline-first</option>
378
- <option value="device-only">device-only</option>
379
- </select>
380
- </label>
381
- <label style={{ fontSize: 'var(--sv-font-size-sm)' }}>
382
- <input
383
- type="checkbox"
384
- checked={deviceOnlyAvailable}
385
- onChange={(e) => setDeviceOnlyAvailable(e.target.checked)}
386
- />{' '}
387
- deviceOnlyAvailable
388
- </label>
389
- </div>
390
- <div
391
- style={{
392
- padding: 'var(--sv-space-4)',
393
- borderRadius: 'var(--sv-radius-md)',
394
- background:
395
- state === 'connectivity-dimmed'
396
- ? 'var(--sv-color-warning-surface)'
397
- : state === 'capability-restricted'
398
- ? 'var(--sv-color-info-surface)'
399
- : 'var(--sv-color-success-surface)',
400
- color:
401
- state === 'connectivity-dimmed'
402
- ? 'var(--sv-color-warning-text)'
403
- : state === 'capability-restricted'
404
- ? 'var(--sv-color-info-text)'
405
- : 'var(--sv-color-success-text)',
406
- fontFamily: ff,
407
- fontSize: 'var(--sv-font-size-sm)',
408
- fontWeight: 600,
409
- textAlign: 'center',
410
- }}
411
- >
412
- useOfflineTileState() → {String(state)}
413
- </div>
414
- <p
415
- style={{
416
- margin: 0,
417
- fontFamily: ff,
418
- fontSize: 'var(--sv-font-size-xs)',
419
- color: 'var(--sv-color-text-muted)',
420
- }}
421
- >
422
- connectivity-dimmed also reacts live to DevTools &gt; Network &gt; Offline — try it with
423
- tier set to (none).
424
- </p>
425
- </div>
426
- );
427
- }
428
-
429
- function SwipeRevealDemo() {
430
- const [open, setOpen] = useState(false);
431
- const [events, setEvents] = useState<string[]>([]);
432
- const log = (msg: string) =>
433
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
434
- const { rowRef, handlers } = useSwipeReveal({
435
- revealWidth: 88,
436
- open,
437
- onOpen: () => {
438
- setOpen(true);
439
- log('opened');
440
- },
441
- onClose: () => {
442
- setOpen(false);
443
- log('closed');
444
- },
445
- });
446
-
447
- return (
448
- <div>
449
- <div
450
- style={{
451
- position: 'relative',
452
- overflow: 'hidden',
453
- borderRadius: 'var(--sv-radius-md)',
454
- border: '1px solid var(--sv-color-border)',
455
- }}
456
- >
457
- <div
458
- style={{
459
- position: 'absolute',
460
- inset: 0,
461
- display: 'flex',
462
- justifyContent: 'flex-end',
463
- }}
464
- >
465
- <button
466
- type="button"
467
- onClick={() => {
468
- setOpen(false);
469
- log('Delete tapped');
470
- }}
471
- style={{
472
- width: 88,
473
- border: 'none',
474
- background: 'var(--sv-color-error-surface)',
475
- color: 'var(--sv-color-error-text)',
476
- fontFamily: ff,
477
- fontSize: 'var(--sv-font-size-sm)',
478
- fontWeight: 600,
479
- cursor: 'pointer',
480
- }}
481
- >
482
- Delete
483
- </button>
484
- </div>
485
- <div
486
- ref={rowRef}
487
- {...handlers}
488
- style={{
489
- position: 'relative',
490
- padding: 'var(--sv-space-4)',
491
- background: 'var(--sv-color-surface)',
492
- fontFamily: ff,
493
- fontSize: 'var(--sv-font-size-sm)',
494
- color: 'var(--sv-color-text-primary)',
495
- touchAction: 'pan-y',
496
- transform: open ? 'translateX(-88px)' : undefined,
497
- transition: 'transform 150ms ease-out',
498
- }}
499
- >
500
- Drag me left to reveal Delete
501
- </div>
502
- </div>
503
- <EventLog events={events} />
504
- <Callout type="info">
505
- Drag with a mouse in this preview, or touch on a real device/device toolbar. The hook only
506
- writes an imperative transform during the drag itself — the CSS transition above only takes
507
- over once the gesture resolves to open or closed on release.
508
- </Callout>
509
- </div>
510
- );
511
- }
512
-
513
- function SnapCarouselDemo() {
514
- const slides = ['Lists', 'Groceries', 'Errands'];
515
- const [index, setIndex] = useState(0);
516
- const [events, setEvents] = useState<string[]>([]);
517
- const log = (msg: string) =>
518
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
519
- const { scrollRef, scrollToIndex } = useSnapCarousel({
520
- itemCount: slides.length,
521
- onSettle: (i) => {
522
- setIndex(i);
523
- log(`settled on slide ${i}`);
524
- },
525
- });
526
-
527
- return (
528
- <div>
529
- <div
530
- ref={scrollRef}
531
- style={{
532
- display: 'flex',
533
- overflowX: 'auto',
534
- scrollSnapType: 'x mandatory',
535
- borderRadius: 'var(--sv-radius-md)',
536
- border: '1px solid var(--sv-color-border)',
537
- }}
538
- >
539
- {slides.map((label, i) => (
540
- <div
541
- key={label}
542
- style={{
543
- flex: '0 0 100%',
544
- scrollSnapAlign: 'start',
545
- padding: 'var(--sv-space-6)',
546
- textAlign: 'center',
547
- fontFamily: ff,
548
- fontSize: 'var(--sv-font-size-sm)',
549
- color: 'var(--sv-color-text-primary)',
550
- background:
551
- i === index ? 'var(--sv-color-surface-sunken)' : 'var(--sv-color-surface)',
552
- }}
553
- >
554
- {label}
555
- </div>
556
- ))}
557
- </div>
558
- <div style={{ display: 'flex', gap: 'var(--sv-space-2)', marginTop: 'var(--sv-space-3)' }}>
559
- {slides.map((label, i) => (
560
- <button
561
- key={label}
562
- type="button"
563
- onClick={() => scrollToIndex(i)}
564
- style={{
565
- padding: 'var(--sv-space-1) var(--sv-space-3)',
566
- borderRadius: 'var(--sv-radius-md)',
567
- border: '1px solid var(--sv-color-border)',
568
- background: i === index ? 'var(--sv-color-accent)' : 'var(--sv-color-surface)',
569
- color:
570
- i === index ? 'var(--sv-color-text-on-accent)' : 'var(--sv-color-text-primary)',
571
- fontFamily: ff,
572
- fontSize: '0.75rem',
573
- cursor: 'pointer',
574
- }}
575
- >
576
- Slide {i}
577
- </button>
578
- ))}
579
- </div>
580
- <EventLog events={events} />
581
- <Callout type="info">
582
- Swipe or scroll the strip above horizontally, or use the buttons. Settle detection is
583
- debounced (120ms default) rather than tied to the <code>scrollend</code> event, which
584
- pre-17.4 iOS Safari/WKWebView doesn&apos;t support.
585
- </Callout>
586
- </div>
587
- );
588
- }
589
-
590
- function ResponsiveLayoutDemo() {
591
- const { isMobile, value } = useResponsiveLayout({
592
- web: (
593
- <div
594
- style={{
595
- padding: 'var(--sv-space-6)',
596
- textAlign: 'center',
597
- fontFamily: ff,
598
- fontSize: 'var(--sv-font-size-sm)',
599
- color: 'var(--sv-color-text-primary)',
600
- }}
601
- >
602
- Web tree — a three-column layout, for example.
603
- </div>
604
- ),
605
- mobile: (
606
- <div
607
- style={{
608
- padding: 'var(--sv-space-6)',
609
- textAlign: 'center',
610
- fontFamily: ff,
611
- fontSize: 'var(--sv-font-size-sm)',
612
- color: 'var(--sv-color-text-primary)',
613
- }}
614
- >
615
- Mobile tree — an entirely different component, not a CSS squeeze.
616
- </div>
617
- ),
618
- });
619
-
620
- return (
621
- <div>
622
- <div
623
- style={{
624
- borderRadius: 'var(--sv-radius-md)',
625
- border: '1px solid var(--sv-color-border)',
626
- background: 'var(--sv-color-surface)',
627
- }}
628
- >
629
- {value}
630
- </div>
631
- <Callout type="info">
632
- Currently showing the <strong>{isMobile ? 'mobile' : 'web'}</strong> tree. Resize the
633
- Storybook viewport (or the toolbar&apos;s viewport picker) below 768px to see it swap — only
634
- the active side is ever mounted, the other tree doesn&apos;t exist in the DOM at all.
635
- </Callout>
636
- </div>
637
- );
638
- }
639
-
640
- function CarouselRouteSyncDemo() {
641
- const PATHS = ['/tasks', '/tasks/starred', '/tasks/groceries'];
642
- const LABELS = ['Lists', 'Starred', 'Groceries'];
643
- const [pathname, setPathname] = useState(PATHS[0] as string);
644
- const [events, setEvents] = useState<string[]>([]);
645
- const log = (msg: string) =>
646
- setEvents((e) => [...e, `${new Date().toLocaleTimeString()} — ${msg}`]);
647
-
648
- const { activeIndex, onSettle } = useCarouselRouteSync({
649
- indexForPathname: (p) => Math.max(0, PATHS.indexOf(p)),
650
- pathForIndex: (i) => PATHS[i] ?? '/tasks',
651
- pathname,
652
- onNavigate: (path) => {
653
- log(`onNavigate("${path}") — simulating router.replace`);
654
- setPathname(path);
655
- },
656
- });
657
-
658
- return (
659
- <div>
660
- <div style={{ display: 'flex', gap: 'var(--sv-space-2)', marginBottom: 'var(--sv-space-3)' }}>
661
- {LABELS.map((label, i) => (
662
- <button
663
- key={label}
664
- type="button"
665
- onClick={() => {
666
- log(`swipe settled on "${label}" (index ${i})`);
667
- onSettle(i);
668
- }}
669
- style={{
670
- padding: 'var(--sv-space-2) var(--sv-space-3)',
671
- borderRadius: 'var(--sv-radius-md)',
672
- border: '1px solid var(--sv-color-border)',
673
- background: i === activeIndex ? 'var(--sv-color-accent)' : 'var(--sv-color-surface)',
674
- color:
675
- i === activeIndex
676
- ? 'var(--sv-color-text-on-accent)'
677
- : 'var(--sv-color-text-primary)',
678
- fontFamily: ff,
679
- fontSize: '0.8rem',
680
- cursor: 'pointer',
681
- }}
682
- >
683
- {label}
684
- </button>
685
- ))}
686
- <button
687
- type="button"
688
- onClick={() => {
689
- const other = PATHS[(activeIndex + 1) % PATHS.length] as string;
690
- log(`external nav to "${other}" (e.g. a tapped <Link>, browser back/forward)`);
691
- setPathname(other);
692
- }}
693
- style={{
694
- padding: 'var(--sv-space-2) var(--sv-space-3)',
695
- borderRadius: 'var(--sv-radius-md)',
696
- border: '1px dashed var(--sv-color-border)',
697
- background: 'var(--sv-color-surface)',
698
- color: 'var(--sv-color-text-primary)',
699
- fontFamily: ff,
700
- fontSize: '0.8rem',
701
- cursor: 'pointer',
702
- }}
703
- >
704
- Simulate external nav
705
- </button>
706
- </div>
707
- <EventLog events={events} />
708
- <Callout type="info">
709
- This demo fakes a router with local <code>useState</code> — in a real app, pass{' '}
710
- <code>next/navigation</code>&apos;s <code>usePathname()</code> as <code>pathname</code> and{' '}
711
- <code>router.replace</code> as <code>onNavigate</code>. Note the &quot;swipe settled&quot;
712
- buttons never log a redundant external-nav resync afterwards — that&apos;s the isInternalNav
713
- dance being handled internally.
714
- </Callout>
715
- </div>
716
- );
717
- }
718
-
719
- // ---------------------------------------------------------------------------
720
- // Main story component
721
- // ---------------------------------------------------------------------------
722
-
723
- function InteractionHooksDoc() {
724
- return (
725
- <div
726
- style={{
727
- padding: 'var(--sv-space-6)',
728
- background: 'var(--sv-color-surface)',
729
- minHeight: '100vh',
730
- fontFamily: ff,
731
- maxWidth: 760,
732
- }}
733
- >
734
- <div style={{ marginBottom: 'var(--sv-space-8)' }}>
735
- <Heading level={1}>Interaction Hooks</Heading>
736
- <Body>
737
- Touch gesture handling, carried once in the design system so no plugin has to rediscover
738
- the failure modes. Per the DS-first principle, build gesture handling here — not in a
739
- plugin. See{' '}
740
- <code style={{ fontFamily: 'var(--sv-font-family-mono)', fontSize: '0.8em' }}>
741
- docs/design-system.md
742
- </code>{' '}
743
- for the full written reference.
744
- </Body>
745
- </div>
746
-
747
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
748
- <SectionHeader
749
- title="useLongPress"
750
- subtitle="Touch-and-hold with movement tolerance, pointercancel handling, OS-callout suppression, and time-boxed click suppression."
751
- />
752
- <Card padding="md">
753
- <LongPressDemo />
754
- </Card>
755
- <CodeBlock>{`const longPress = useLongPress({ onLongPress: () => setBulkMode(true) });
756
- <div {...longPress}>Hold to select</div>`}</CodeBlock>
757
- </section>
758
-
759
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
760
- <SectionHeader
761
- title="useDoubleTapHandler / useSingleOrDoubleTap"
762
- subtitle="Desktop double-click reports e.detail === 2 natively; touch needs timing-based detection instead."
763
- />
764
- <Card padding="md">
765
- <DoubleTapDemo />
766
- </Card>
767
- <Callout type="tip">
768
- Use <code style={{ fontFamily: 'var(--sv-font-family-mono)' }}>useDoubleTapHandler</code>{' '}
769
- when the single tap has nothing to cancel. Use{' '}
770
- <code style={{ fontFamily: 'var(--sv-font-family-mono)' }}>useSingleOrDoubleTap</code>{' '}
771
- only when the single tap has a default action (e.g. navigation) a following double-tap
772
- must be able to preempt — every single tap through it pays the ~350ms wait.
773
- </Callout>
774
- </section>
775
-
776
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
777
- <SectionHeader
778
- title="useCommitOnEnterOrBlur"
779
- subtitle="Unifies Enter-to-commit with iOS's native keyboard accessory toolbar, whose Done/checkmark only ever fires a blur, never a keydown."
780
- />
781
- <Card padding="md">
782
- <CommitOnEnterOrBlurDemo />
783
- </Card>
784
- <CodeBlock>{`const commitHandlers = useCommitOnEnterOrBlur(() => createTask(title));
785
- <input value={title} onChange={...} {...commitHandlers} />`}</CodeBlock>
786
- </section>
787
-
788
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
789
- <SectionHeader
790
- title="useIsMobile"
791
- subtitle="SSR-safe viewport check against the platform's single documented breakpoint (768px)."
792
- />
793
- <Card padding="md">
794
- <IsMobileDemo />
795
- </Card>
796
- <CodeBlock>{`import { useIsMobile, MOBILE_BREAKPOINT_PX } from '@sovereignfs/ui';
797
-
798
- const isMobile = useIsMobile(); // defaults to MOBILE_BREAKPOINT_PX (768)`}</CodeBlock>
799
- </section>
800
-
801
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
802
- <SectionHeader
803
- title="useIsOffline"
804
- subtitle="SSR-safe navigator.onLine tracking, shared by OfflineBanner, the login page, and Console/Account's offline gate (research 0012)."
805
- />
806
- <Card padding="md">
807
- <IsOfflineDemo />
808
- </Card>
809
- <CodeBlock>{`import { useIsOffline } from '@sovereignfs/ui';
810
-
811
- const isOffline = useIsOffline();`}</CodeBlock>
812
- </section>
813
-
814
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
815
- <SectionHeader
816
- title="useOfflineTileState"
817
- subtitle="Which of the two app-tile states, if any, applies given a plugin's declared offline tier — connectivity-dimmed (no tier, offline right now) vs. capability-restricted (device-only, unavailable here), never conflated (research 0012)."
818
- />
819
- <Card padding="md">
820
- <OfflineTileStateDemo />
821
- </Card>
822
- <CodeBlock>{`import { useOfflineTileState } from '@sovereignfs/ui';
823
-
824
- // deviceOnlyAvailable comes from isDeviceOnlyTierAvailable() in
825
- // @sovereignfs/sdk/device-client — passed in, not computed here, so
826
- // @sovereignfs/ui never depends on @sovereignfs/sdk.
827
- const state = useOfflineTileState(plugin.offline, deviceOnlyAvailable);
828
- // 'connectivity-dimmed' | 'capability-restricted' | null`}</CodeBlock>
829
- </section>
830
-
831
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
832
- <SectionHeader
833
- title="useSwipeReveal"
834
- subtitle="Horizontal swipe-to-reveal for a row's Done/Delete actions — extracted from sovereign-tasks' two independent hand-rolled implementations (RFC 0079)."
835
- />
836
- <Card padding="md">
837
- <SwipeRevealDemo />
838
- </Card>
839
- <CodeBlock>{`const { rowRef, handlers } = useSwipeReveal({
840
- revealWidth: 88,
841
- open,
842
- onOpen: () => setOpen(true),
843
- onClose: () => setOpen(false),
844
- });
845
- <div ref={rowRef} {...handlers} style={{ transform: open ? 'translateX(-88px)' : undefined }}>
846
- Row content
847
- </div>`}</CodeBlock>
848
- </section>
849
-
850
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
851
- <SectionHeader
852
- title="useSnapCarousel"
853
- subtitle="Debounced settled-slide detection over a native scroll-snap container — extracted from sovereign-tasks and sovereign-shopper's independently duplicated carousels (RFC 0079)."
854
- />
855
- <Card padding="md">
856
- <SnapCarouselDemo />
857
- </Card>
858
- <CodeBlock>{`const { scrollRef, scrollToIndex } = useSnapCarousel({
859
- itemCount: slides.length,
860
- onSettle: (index) => setActiveIndex(index),
861
- });
862
- <div ref={scrollRef} style={{ display: 'flex', overflowX: 'auto', scrollSnapType: 'x mandatory' }}>
863
- {slides.map((slide) => <div style={{ scrollSnapAlign: 'start' }}>{slide}</div>)}
864
- </div>`}</CodeBlock>
865
- </section>
866
-
867
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
868
- <SectionHeader
869
- title="useResponsiveLayout"
870
- subtitle="Picks between a web and mobile value for the current viewport — formalizes the 'render an entirely different tree below a breakpoint' fork plugins have hand-rolled per plugin. See also the ResponsiveSurface component for the equivalent as plain JSX."
871
- />
872
- <Card padding="md">
873
- <ResponsiveLayoutDemo />
874
- </Card>
875
- <CodeBlock>{`const { isMobile, value } = useResponsiveLayout({ web: <WebShell />, mobile: <MobileShell /> });
876
- // or, as a component:
877
- <ResponsiveSurface web={<WebShell />} mobile={<MobileShell />} />`}</CodeBlock>
878
- </section>
879
-
880
- <section style={{ marginBottom: 'var(--sv-space-10)' }}>
881
- <SectionHeader
882
- title="useCarouselRouteSync"
883
- subtitle="Router-agnostic pathname↔slide-index sync for SwipableMobileCarousel — centralizes the isInternalNav dance both sovereign-tasks and sovereign-shopper hand-roll identically today."
884
- />
885
- <Card padding="md">
886
- <CarouselRouteSyncDemo />
887
- </Card>
888
- <CodeBlock>{`const { activeIndex, onSettle } = useCarouselRouteSync({
889
- indexForPathname: (p) => indexForPathname(p, lists), // your plugin's own logic, unchanged
890
- pathForIndex: (i) => pathForIndex(i, lists),
891
- pathname: usePathname(),
892
- onNavigate: (path) => router.replace(path, { scroll: false }),
893
- });
894
- <SwipableMobileCarousel activeIndex={activeIndex} onSettle={onSettle} aria-label="Task lists">
895
- ...
896
- </SwipableMobileCarousel>`}</CodeBlock>
897
- </section>
898
- </div>
899
- );
900
- }
901
-
902
- // ---------------------------------------------------------------------------
903
-
904
- const meta = {
905
- title: 'Overview/Interaction Hooks',
906
- component: InteractionHooksDoc,
907
- parameters: {
908
- layout: 'fullscreen',
909
- docs: {
910
- description: {
911
- component:
912
- 'Reference and live demos for the touch-gesture hooks exported from @sovereignfs/ui. Long-press requires real touch input to trigger — use the devtools device toolbar or a physical device.',
913
- },
914
- },
915
- },
916
- } satisfies Meta<typeof InteractionHooksDoc>;
917
-
918
- export default meta;
919
- type Story = StoryObj<typeof meta>;
920
-
921
- export const Default: Story = {};
922
-
923
- export const MobileView: Story = {
924
- parameters: { viewport: { defaultViewport: 'mobile' } },
925
- };