@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,144 +0,0 @@
1
- import { useMemo, useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { SuggestionInput, type SuggestionOption } from './SuggestionInput';
4
-
5
- const meta = {
6
- title: 'Components/SuggestionInput',
7
- component: SuggestionInput,
8
- parameters: {
9
- layout: 'padded',
10
- docs: {
11
- description: {
12
- component:
13
- 'A text field with an anchored, keyboard-navigable list of async suggestions, plus an optional trailing "create new" row so free text is always a valid commit.',
14
- },
15
- },
16
- },
17
- args: {
18
- value: '',
19
- onChange: () => {},
20
- options: [],
21
- onSelect: () => {},
22
- 'aria-label': 'Add an item',
23
- },
24
- } satisfies Meta<typeof SuggestionInput>;
25
-
26
- export default meta;
27
- type Story = StoryObj<typeof meta>;
28
-
29
- const CATALOG: SuggestionOption[] = [
30
- { id: '1', label: 'Bananas', icon: '🍌', meta: 'bought 4× recently' },
31
- { id: '2', label: 'Banana bread mix', icon: '🍞' },
32
- { id: '3', label: 'Milk', icon: '🥛' },
33
- { id: '4', label: 'Eggs', icon: '🥚' },
34
- { id: '5', label: 'Olive oil', icon: '🫒' },
35
- ];
36
-
37
- function ControlledSuggestionInput({ withCreateRow = true }: { withCreateRow?: boolean }) {
38
- const [value, setValue] = useState('');
39
- const [selected, setSelected] = useState<string | null>(null);
40
- const options = useMemo(
41
- () =>
42
- value.trim()
43
- ? CATALOG.filter((c) => c.label.toLowerCase().includes(value.trim().toLowerCase()))
44
- : [],
45
- [value],
46
- );
47
-
48
- return (
49
- <div style={{ width: 320 }}>
50
- <SuggestionInput
51
- value={value}
52
- onChange={setValue}
53
- options={options}
54
- onSelect={(option) => {
55
- setSelected(option.label);
56
- setValue('');
57
- }}
58
- placeholder="Add an item…"
59
- aria-label="Add an item"
60
- createLabel={withCreateRow ? (v) => `Add "${v}" as a new item` : undefined}
61
- onCreate={
62
- withCreateRow
63
- ? (v) => {
64
- setSelected(v);
65
- setValue('');
66
- }
67
- : undefined
68
- }
69
- />
70
- {selected && <p style={{ marginTop: 12, fontSize: 13 }}>Added: {selected}</p>}
71
- </div>
72
- );
73
- }
74
-
75
- export const Default: Story = {
76
- render: () => <ControlledSuggestionInput />,
77
- };
78
-
79
- export const NoCreateRow: Story = {
80
- name: 'Without create row (matched options only)',
81
- render: () => <ControlledSuggestionInput withCreateRow={false} />,
82
- };
83
-
84
- export const OpenWithOptions: Story = {
85
- render: () => (
86
- <div style={{ width: 320 }}>
87
- <SuggestionInput
88
- value="ban"
89
- onChange={() => {}}
90
- options={CATALOG.slice(0, 2)}
91
- onSelect={() => {}}
92
- aria-label="Add an item"
93
- createLabel={(v) => `Add "${v}" as a new item`}
94
- onCreate={() => {}}
95
- />
96
- </div>
97
- ),
98
- };
99
-
100
- export const Loading: Story = {
101
- render: () => (
102
- <div style={{ width: 320 }}>
103
- <SuggestionInput
104
- value="ban"
105
- onChange={() => {}}
106
- options={[]}
107
- onSelect={() => {}}
108
- loading
109
- aria-label="Add an item"
110
- />
111
- </div>
112
- ),
113
- };
114
-
115
- export const Empty: Story = {
116
- name: 'Empty (no matches, no create row)',
117
- render: () => (
118
- <div style={{ width: 320 }}>
119
- <SuggestionInput
120
- value="xyz"
121
- onChange={() => {}}
122
- options={[]}
123
- onSelect={() => {}}
124
- aria-label="Add an item"
125
- />
126
- </div>
127
- ),
128
- };
129
-
130
- export const Disabled: Story = {
131
- render: () => (
132
- <div style={{ width: 320 }}>
133
- <SuggestionInput
134
- value=""
135
- onChange={() => {}}
136
- options={[]}
137
- onSelect={() => {}}
138
- disabled
139
- placeholder="Add an item…"
140
- aria-label="Add an item"
141
- />
142
- </div>
143
- ),
144
- };
@@ -1,207 +0,0 @@
1
- 'use client';
2
-
3
- import { useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';
4
- import { Popover } from '../Popover/Popover';
5
- import styles from './SuggestionInput.module.css';
6
-
7
- export interface SuggestionOption {
8
- id: string;
9
- label: string;
10
- icon?: ReactNode;
11
- /** Secondary text shown right-aligned on the row, e.g. "bought 4× recently". */
12
- meta?: string;
13
- }
14
-
15
- export interface SuggestionInputProps {
16
- value: string;
17
- onChange: (value: string) => void;
18
- options: SuggestionOption[];
19
- onSelect: (option: SuggestionOption) => void;
20
- placeholder?: string;
21
- 'aria-label': string;
22
- id?: string;
23
- disabled?: boolean;
24
- /** Shown in place of the options list while a suggestion fetch is in flight. */
25
- loading?: boolean;
26
- /**
27
- * Label for a trailing, always-selectable row that commits the raw typed
28
- * text instead of a matched option — e.g. `(v) => \`Add "${v}" as a new item\`}`.
29
- * Shown whenever `value` is non-empty and `onCreate` is provided, even
30
- * when `options` is empty, so the input is never a dead end.
31
- */
32
- createLabel?: (value: string) => string;
33
- onCreate?: (value: string) => void;
34
- className?: string;
35
- }
36
-
37
- /**
38
- * SuggestionInput — a text field with an anchored, keyboard-navigable list
39
- * of async suggestions (a combobox), plus an optional trailing "create new"
40
- * row so free text is always a valid commit, not just a matched option.
41
- *
42
- * Fully controlled: the caller owns `value`/`onChange` and supplies
43
- * `options` (e.g. debounced server-fetched results) — this component only
44
- * handles open/close, keyboard navigation, and selection. Built on `Popover`
45
- * for positioning (`width: 'trigger'`, so the panel always matches the
46
- * input's own width).
47
- */
48
- export function SuggestionInput({
49
- value,
50
- onChange,
51
- options,
52
- onSelect,
53
- placeholder,
54
- 'aria-label': ariaLabel,
55
- id,
56
- disabled = false,
57
- loading = false,
58
- createLabel,
59
- onCreate,
60
- className,
61
- }: SuggestionInputProps) {
62
- const generatedId = useId();
63
- const inputId = id ?? generatedId;
64
- const listId = `${inputId}-suggestions`;
65
- const inputRef = useRef<HTMLInputElement>(null);
66
- const [focused, setFocused] = useState(false);
67
- const [activeIndex, setActiveIndex] = useState(-1);
68
-
69
- const showCreateRow = Boolean(onCreate && createLabel && value.trim());
70
- const rowCount = options.length + (showCreateRow ? 1 : 0);
71
- const open = focused && (rowCount > 0 || loading);
72
-
73
- function close() {
74
- setFocused(false);
75
- setActiveIndex(-1);
76
- }
77
-
78
- function commitIndex(index: number) {
79
- if (index < 0 || index >= rowCount) return;
80
- const option = options[index];
81
- if (option) {
82
- onSelect(option);
83
- } else if (onCreate) {
84
- onCreate(value);
85
- }
86
- close();
87
- }
88
-
89
- function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {
90
- if (!open) return;
91
- // Some synthetic input sources (seen from automated/CDP-driven key
92
- // dispatch) send a keydown with `key`/`code` as "Unidentified" or empty
93
- // and no `keyCode` either — nothing here can special-case that further,
94
- // but checking the legacy numeric code costs nothing and covers sources
95
- // that do populate it even when `key` doesn't (older browsers, some
96
- // assistive tech, IME edge cases).
97
- const isArrowDown = e.key === 'ArrowDown' || e.keyCode === 40;
98
- const isArrowUp = e.key === 'ArrowUp' || e.keyCode === 38;
99
- const isEnter = e.key === 'Enter' || e.keyCode === 13;
100
- const isEscape = e.key === 'Escape' || e.keyCode === 27;
101
-
102
- if (isArrowDown) {
103
- e.preventDefault();
104
- setActiveIndex((i) => (i + 1) % rowCount);
105
- } else if (isArrowUp) {
106
- e.preventDefault();
107
- setActiveIndex((i) => (i <= 0 ? rowCount - 1 : i - 1));
108
- } else if (isEnter) {
109
- e.preventDefault();
110
- commitIndex(activeIndex === -1 ? 0 : activeIndex);
111
- } else if (isEscape) {
112
- close();
113
- }
114
- }
115
-
116
- const trigger = (
117
- <input
118
- ref={inputRef}
119
- id={inputId}
120
- type="text"
121
- role="combobox"
122
- aria-expanded={open}
123
- aria-controls={listId}
124
- aria-autocomplete="list"
125
- aria-activedescendant={activeIndex >= 0 ? `${listId}-option-${activeIndex}` : undefined}
126
- aria-label={ariaLabel}
127
- className={[styles.input, className].filter(Boolean).join(' ')}
128
- value={value}
129
- placeholder={placeholder}
130
- disabled={disabled}
131
- autoComplete="off"
132
- onChange={(e) => {
133
- onChange(e.target.value);
134
- setActiveIndex(-1);
135
- }}
136
- onFocus={() => setFocused(true)}
137
- onKeyDown={handleKeyDown}
138
- />
139
- );
140
-
141
- return (
142
- <Popover
143
- trigger={trigger}
144
- open={open}
145
- onClose={close}
146
- width="trigger"
147
- aria-label={`${ariaLabel} suggestions`}
148
- >
149
- <ul id={listId} role="listbox" className={styles.list}>
150
- {loading ? (
151
- <li className={styles.status}>Loading…</li>
152
- ) : (
153
- <>
154
- {options.map((option, index) => (
155
- <li key={option.id} role="none">
156
- <button
157
- id={`${listId}-option-${index}`}
158
- role="option"
159
- aria-selected={index === activeIndex}
160
- type="button"
161
- className={[styles.option, index === activeIndex ? styles.optionActive : '']
162
- .filter(Boolean)
163
- .join(' ')}
164
- // Selecting via mouse fires before the input's blur — use
165
- // onMouseDown (not onClick) so the click doesn't lose focus
166
- // and close the popover before the selection registers.
167
- onMouseDown={(e) => {
168
- e.preventDefault();
169
- commitIndex(index);
170
- }}
171
- >
172
- {option.icon && <span className={styles.optionIcon}>{option.icon}</span>}
173
- <span className={styles.optionLabel}>{option.label}</span>
174
- {option.meta && <span className={styles.optionMeta}>{option.meta}</span>}
175
- </button>
176
- </li>
177
- ))}
178
- {showCreateRow && createLabel && (
179
- <li role="none">
180
- {options.length > 0 && <div className={styles.divider} />}
181
- <button
182
- id={`${listId}-option-${options.length}`}
183
- role="option"
184
- aria-selected={options.length === activeIndex}
185
- type="button"
186
- className={[
187
- styles.option,
188
- styles.optionCreate,
189
- options.length === activeIndex ? styles.optionActive : '',
190
- ]
191
- .filter(Boolean)
192
- .join(' ')}
193
- onMouseDown={(e) => {
194
- e.preventDefault();
195
- commitIndex(options.length);
196
- }}
197
- >
198
- {createLabel(value)}
199
- </button>
200
- </li>
201
- )}
202
- </>
203
- )}
204
- </ul>
205
- </Popover>
206
- );
207
- }
@@ -1,64 +0,0 @@
1
- .wrap {
2
- position: relative;
3
- height: 100%;
4
- width: 100%;
5
- }
6
-
7
- .scroller {
8
- height: 100%;
9
- width: 100%;
10
- display: flex;
11
- overflow-x: auto;
12
- overflow-y: hidden;
13
- scroll-snap-type: x mandatory;
14
- /* Momentum + rubber-banding come from the browser's native scroll physics —
15
- no hand-rolled pointer/touch dragging. Deliberately NOT
16
- -webkit-overflow-scrolling: touch: that legacy iOS <13 hint promotes its
17
- element to its own compositing layer for GPU-accelerated momentum
18
- scroll, and that layer's paint order relative to siblings/fixed
19
- descendants elsewhere in the tree isn't always reliable on real iOS
20
- Safari (confirmed via sovereign-tasks' and sovereign-shopper's own
21
- carousels, which hit and fixed this exact bug — a position:fixed
22
- overlay opened above the scroller painted BEHIND it instead of above).
23
- Removing it doesn't disable momentum scrolling on any iOS version this
24
- platform realistically targets. */
25
- }
26
-
27
- .slide {
28
- flex: 0 0 100%;
29
- width: 100%;
30
- height: 100%;
31
- min-width: 0;
32
- overflow: hidden;
33
- scroll-snap-align: start;
34
- scroll-snap-stop: always;
35
- /* Slide content is a flex column so Header/Footer stay their natural size
36
- and Body (flex: 1 1 auto, min-height: 0) fills and scrolls the rest —
37
- see SwipableMobileCarouselSlideParts.module.css. */
38
- display: flex;
39
- flex-direction: column;
40
- }
41
-
42
- .indicatorSlot {
43
- /* Overlays the bottom of .wrap rather than taking its own layout row —
44
- matches both sovereign-tasks' and sovereign-shopper's existing dots
45
- placement. Applied by the carousel itself around WHATEVER
46
- renderIndicator returns (the default SwipableMobileCarouselDots or a
47
- caller-supplied override) — a custom renderIndicator has no way to
48
- import this module's locally-scoped class itself (CSS Modules classnames
49
- aren't cross-file importable), so positioning must live here, not be
50
- something each indicator implementation opts into. Previously this class
51
- was only ever applied to the *default* indicator branch, which silently
52
- left any custom renderIndicator unpositioned — a static, in-flow sibling
53
- pushed below the full-height .scroller and clipped out of view instead
54
- of overlaid on top of it. */
55
- position: absolute;
56
- left: 0;
57
- right: 0;
58
- bottom: var(--sv-space-3);
59
- pointer-events: none;
60
- }
61
-
62
- .indicatorSlot > * {
63
- pointer-events: auto;
64
- }
@@ -1,243 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- Children,
5
- isValidElement,
6
- useEffect,
7
- useLayoutEffect,
8
- useMemo,
9
- useRef,
10
- type ReactElement,
11
- type ReactNode,
12
- } from 'react';
13
- import { useSnapCarousel } from '../../hooks/useSnapCarousel';
14
- import { SwipableMobileCarouselDots } from '../SwipableMobileCarouselDots/SwipableMobileCarouselDots';
15
- import { SwipableMobileCarouselSlide } from './SwipableMobileCarouselSlide';
16
- import { CarouselSlideMountContext } from './context';
17
- import styles from './SwipableMobileCarousel.module.css';
18
-
19
- export interface SwipableMobileCarouselIndicatorProps {
20
- count: number;
21
- activeIndex: number;
22
- labels: (string | undefined)[];
23
- onJump: (index: number) => void;
24
- }
25
-
26
- export interface SwipableMobileCarouselProps {
27
- /** Controlled active slide index — the caller owns this (typically via
28
- * useCarouselRouteSync, or plain useState). */
29
- activeIndex: number;
30
- /** Called when a swipe gesture settles on a different index, or when the
31
- * reorder-jump fix re-snaps after the active slide's position changes.
32
- * The caller is responsible for updating `activeIndex` in response. */
33
- onSettle: (index: number) => void;
34
- /** How many slides on each side of the active one stay mounted. Default 1
35
- * matches both sovereign-tasks' and sovereign-shopper's existing "swipe
36
- * never shows a spinner" behavior. Slides outside this window keep their
37
- * DOM slot (so scroll-snap's position-based indexing stays correct) but
38
- * their children are not mounted at all. */
39
- prefetchDistance?: number;
40
- /** Passed straight through to the internal useSnapCarousel. */
41
- settleDebounceMs?: number;
42
- /** Required — labels the scroller region for assistive tech. No generic
43
- * fallback, since one would be wrong for every actual consumer. */
44
- 'aria-label': string;
45
- /** Renders the indicator. Defaults to SwipableMobileCarouselDots. Pass
46
- * `null` to render no indicator at all. */
47
- renderIndicator?: null | ((props: SwipableMobileCarouselIndicatorProps) => ReactNode);
48
- className?: string;
49
- /** Must be SwipableMobileCarouselSlide elements (nullish/boolean children
50
- * are safely skipped for conditional slides). A dev-mode warning is
51
- * logged for any other child type — see resolveSlides below. */
52
- children: ReactNode;
53
- }
54
-
55
- interface ResolvedSlide {
56
- key: string;
57
- label: string | undefined;
58
- element: ReactElement;
59
- }
60
-
61
- function describeChild(child: unknown): string {
62
- if (isValidElement(child)) {
63
- const type = child.type;
64
- if (typeof type === 'string') return `<${type}>`;
65
- if (typeof type === 'function') {
66
- const named = type as { displayName?: string; name?: string };
67
- return `<${named.displayName ?? named.name ?? 'Component'}>`;
68
- }
69
- return '<unknown>';
70
- }
71
- if (typeof child === 'string') return `string "${child}"`;
72
- return String(child);
73
- }
74
-
75
- function resolveSlides(children: ReactNode): ResolvedSlide[] {
76
- const slides: ResolvedSlide[] = [];
77
- Children.forEach(children, (child, index) => {
78
- if (child === null || child === undefined || child === false || child === true) return;
79
- if (!isValidElement(child) || child.type !== SwipableMobileCarouselSlide) {
80
- if (process.env.NODE_ENV !== 'production') {
81
- console.error(
82
- '[SwipableMobileCarousel] Every child must be a <SwipableMobileCarouselSlide>. ' +
83
- `Found ${describeChild(child)} at position ${index}. A non-Slide child shifts every ` +
84
- "subsequent slide's index, desyncing scroll-snap position from activeIndex.",
85
- );
86
- }
87
- return;
88
- }
89
- const slideProps = child.props as { slideKey: string; label?: string };
90
- if (process.env.NODE_ENV !== 'production' && !slideProps.label) {
91
- console.warn(
92
- `[SwipableMobileCarousel] SwipableMobileCarouselSlide "${slideProps.slideKey}" has no ` +
93
- 'label — it will show as "Slide N of count" in the default dots indicator.',
94
- );
95
- }
96
- slides.push({ key: slideProps.slideKey, label: slideProps.label, element: child });
97
- });
98
- return slides;
99
- }
100
-
101
- /**
102
- * SwipableMobileCarousel — a compound component for swiping between full-
103
- * width slides (each an independent route/view on mobile), wrapping
104
- * useSnapCarousel. This library's first compound component: every other
105
- * component here is flat/prop-based, but slide content is large, arbitrary,
106
- * per-plugin subtrees that need a header-known/body-loading split an
107
- * array-of-objects prop would only express with worse JSX ergonomics.
108
- *
109
- * Owns rendering and mount-window mechanics only — it has no opinion on
110
- * where slide data lives. Do NOT: (a) aggregate cross-slide data inside a
111
- * SwipableMobileCarouselSlideBody (that recomputes on every slide render
112
- * regardless of which slide is active — belongs in the parent, which
113
- * already knows every slide exists); (b) mount a detail overlay (Sheet,
114
- * Dialog) inside a Slide's children — mount it as a sibling of
115
- * SwipableMobileCarousel instead, controlled by the same state that would
116
- * otherwise drive a routed page's overlay. sovereign-tasks' current
117
- * hand-rolled carousel does both and is measurably laggier than
118
- * sovereign-shopper's equivalent, which keeps its overlay in the routed pane.
119
- */
120
- export function SwipableMobileCarousel({
121
- activeIndex,
122
- onSettle,
123
- prefetchDistance = 1,
124
- settleDebounceMs = 120,
125
- 'aria-label': ariaLabel,
126
- renderIndicator,
127
- className,
128
- children,
129
- }: SwipableMobileCarouselProps) {
130
- const slides = useMemo(() => resolveSlides(children), [children]);
131
- const count = slides.length;
132
- const clampedActiveIndex = count === 0 ? 0 : Math.max(0, Math.min(count - 1, activeIndex));
133
-
134
- // Initial scroll position, once — subsequent activeIndex changes come
135
- // either from the user's own swipe (already reflected in DOM scroll
136
- // position; re-syncing to the same index below is a harmless no-op) or an
137
- // external navigation, which the effect below scrolls to explicitly.
138
- const initialActiveIndexRef = useRef(clampedActiveIndex);
139
-
140
- const { scrollRef, scrollToIndex, liveIndex } = useSnapCarousel({
141
- itemCount: count,
142
- onSettle,
143
- debounceMs: settleDebounceMs,
144
- initialIndex: initialActiveIndexRef.current,
145
- });
146
- useLayoutEffect(() => {
147
- scrollToIndex(initialActiveIndexRef.current, 'instant');
148
- // Runs once on mount only, matching both existing plugins' identical pattern.
149
- }, []);
150
-
151
- const didMountActiveIndexSyncRef = useRef(false);
152
- useEffect(() => {
153
- if (!didMountActiveIndexSyncRef.current) {
154
- didMountActiveIndexSyncRef.current = true;
155
- return;
156
- }
157
- scrollToIndex(clampedActiveIndex, 'smooth');
158
- }, [clampedActiveIndex, scrollToIndex]);
159
-
160
- // Reorder-jump fix: scroll-snap position tracks DOM order, not slide
161
- // identity. If the previously-active slide's key still exists but moved
162
- // (a caller re-sorted their slide array while mounted), re-snap to its
163
- // new position and report it via onSettle so the caller's activeIndex
164
- // stays in sync — otherwise scroll position silently desyncs from slide
165
- // identity. Runs every commit (no dependency array) since it needs to
166
- // notice any children change, not just a specific prop.
167
- const prevKeysRef = useRef<string[] | null>(null);
168
- useLayoutEffect(() => {
169
- const currentKeys = slides.map((s) => s.key);
170
- const prevKeys = prevKeysRef.current;
171
- if (prevKeys) {
172
- const sameOrder =
173
- prevKeys.length === currentKeys.length && prevKeys.every((k, i) => k === currentKeys[i]);
174
- if (!sameOrder) {
175
- const activeKey = prevKeys[clampedActiveIndex];
176
- if (activeKey !== undefined) {
177
- const newIndex = currentKeys.indexOf(activeKey);
178
- if (newIndex !== -1 && newIndex !== clampedActiveIndex) {
179
- scrollToIndex(newIndex, 'instant');
180
- onSettle(newIndex);
181
- }
182
- }
183
- }
184
- }
185
- prevKeysRef.current = currentKeys;
186
- });
187
-
188
- function handleJump(index: number) {
189
- // scrollToIndex sets useSnapCarousel's own dedupe ref synchronously, so
190
- // the natural scroll-settle detection will NOT re-report this index —
191
- // onSettle must be called directly here, same pairing as the
192
- // reorder-jump fix above.
193
- scrollToIndex(index, 'smooth');
194
- onSettle(index);
195
- }
196
-
197
- const labels = slides.map((s) => s.label);
198
- const indicator =
199
- renderIndicator === null ? null : renderIndicator ? (
200
- renderIndicator({ count, activeIndex: clampedActiveIndex, labels, onJump: handleJump })
201
- ) : (
202
- <SwipableMobileCarouselDots
203
- count={count}
204
- activeIndex={clampedActiveIndex}
205
- labels={labels}
206
- aria-label={ariaLabel}
207
- onJump={handleJump}
208
- />
209
- );
210
-
211
- return (
212
- <div className={[styles.wrap, className].filter(Boolean).join(' ')}>
213
- <div className={styles.scroller} ref={scrollRef} role="region" aria-label={ariaLabel}>
214
- {slides.map((slide, i) => (
215
- <div className={styles.slide} key={slide.key}>
216
- <CarouselSlideMountContext.Provider
217
- value={{
218
- // Union of the settled index and the live (real-time,
219
- // pre-settle) scroll position — see useSnapCarousel's own
220
- // liveIndex doc comment. A single fast flick can carry
221
- // native scroll-snap momentum past an intermediate slide to
222
- // one two-or-more away before settle-detection's debounce
223
- // window ever reports it; without also checking liveIndex,
224
- // the slide the container had already visually scrolled to
225
- // stays unmounted (rendering nothing at all, not even a
226
- // loading skeleton) for that entire window.
227
- isMounted:
228
- Math.abs(i - clampedActiveIndex) <= prefetchDistance ||
229
- Math.abs(i - liveIndex) <= prefetchDistance,
230
- }}
231
- >
232
- {slide.element}
233
- </CarouselSlideMountContext.Provider>
234
- </div>
235
- ))}
236
- </div>
237
- {/* Positioning (overlay the bottom of .wrap) lives here, applied around
238
- whatever renderIndicator returns — see .indicatorSlot's own doc
239
- comment for why this can't be delegated to the indicator itself. */}
240
- {indicator && <div className={styles.indicatorSlot}>{indicator}</div>}
241
- </div>
242
- );
243
- }
@@ -1,35 +0,0 @@
1
- 'use client';
2
-
3
- import { useContext, type ReactNode } from 'react';
4
- import { CarouselSlideMountContext } from './context';
5
-
6
- export interface SwipableMobileCarouselSlideProps {
7
- /** Stable identity for this slide, independent of its position among
8
- * siblings — required. This is what makes SwipableMobileCarousel's
9
- * reorder-jump fix possible: a plain array index can't distinguish "this
10
- * slide moved to position 2" from "this slide was removed and a
11
- * different one is now at position 2." Reuse whatever id the caller
12
- * already keys their `.map()` on (e.g. a list's own id). */
13
- slideKey: string;
14
- /** Accessible label surfaced to the default dots indicator (e.g.
15
- * "Groceries"). Falls back to "Slide N of count" if omitted — omitting it
16
- * logs a dev-mode warning, since every real slide usually has a title
17
- * available synchronously already. */
18
- label?: string;
19
- /** SwipableMobileCarouselSlideHeader/Body/Footer, in any order/subset. */
20
- children: ReactNode;
21
- }
22
-
23
- /**
24
- * SwipableMobileCarouselSlide — a single slide of a SwipableMobileCarousel.
25
- * Renders its children only while within the carousel's mount window (the
26
- * active slide ± its configured prefetchDistance); outside that window it
27
- * renders nothing, matching both sovereign-tasks and sovereign-shopper's
28
- * existing "never fetch/render a non-neighbor slide" behavior, now
29
- * centralized instead of hand-rolled per plugin.
30
- */
31
- export function SwipableMobileCarouselSlide({ children }: SwipableMobileCarouselSlideProps) {
32
- const ctx = useContext(CarouselSlideMountContext);
33
- if (!ctx?.isMounted) return null;
34
- return <>{children}</>;
35
- }