@krizaka/ui 3.3.0 → 3.4.0

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 (352) hide show
  1. package/dist/activity-feed.d.ts +199 -0
  2. package/dist/activity-feed.js +155 -0
  3. package/dist/activity-feed.js.map +1 -0
  4. package/dist/argument-card.js +3 -3
  5. package/dist/chunk-7Z4KHPFC.js +42 -0
  6. package/dist/chunk-7Z4KHPFC.js.map +1 -0
  7. package/dist/data-table.js +98 -131
  8. package/dist/data-table.js.map +1 -1
  9. package/dist/description-list.d.ts +105 -0
  10. package/dist/description-list.js +49 -0
  11. package/dist/description-list.js.map +1 -0
  12. package/dist/index.js +13 -66
  13. package/dist/index.js.map +1 -1
  14. package/dist/kanban.d.ts +132 -0
  15. package/dist/kanban.js +187 -0
  16. package/dist/kanban.js.map +1 -0
  17. package/dist/list.d.ts +153 -0
  18. package/dist/list.js +130 -0
  19. package/dist/list.js.map +1 -0
  20. package/dist/map.d.ts +463 -0
  21. package/dist/map.js +952 -0
  22. package/dist/map.js.map +1 -0
  23. package/dist/motion.css +12 -1
  24. package/dist/native/map.d.ts +200 -0
  25. package/dist/native/map.js +673 -0
  26. package/dist/native/map.js.map +1 -0
  27. package/dist/native/media-picker.d.ts +58 -0
  28. package/dist/native/media-picker.js +63 -0
  29. package/dist/native/media-picker.js.map +1 -0
  30. package/dist/native.d.ts +568 -6
  31. package/dist/native.js +1989 -868
  32. package/dist/native.js.map +1 -1
  33. package/dist/page-hero.js +3 -3
  34. package/dist/stat.d.ts +31 -2
  35. package/dist/stat.js +21 -4
  36. package/dist/stat.js.map +1 -1
  37. package/dist/tree-view.d.ts +111 -0
  38. package/dist/tree-view.js +154 -0
  39. package/dist/tree-view.js.map +1 -0
  40. package/package.json +147 -10
  41. package/registry/achievement.json +1 -1
  42. package/registry/action-bar.json +1 -1
  43. package/registry/action-sheet.json +121 -0
  44. package/registry/activity-feed.json +468 -0
  45. package/registry/alert.json +1 -1
  46. package/registry/app-shell.json +1 -1
  47. package/registry/argument-card.json +1 -1
  48. package/registry/audio-player.json +1 -1
  49. package/registry/auth-layout.json +1 -1
  50. package/registry/avatar.json +58 -3
  51. package/registry/badge.json +1 -1
  52. package/registry/button.json +1 -1
  53. package/registry/card-grid.json +1 -1
  54. package/registry/card.json +1 -1
  55. package/registry/catalogue-page.json +1 -1
  56. package/registry/changelog-page.json +1 -1
  57. package/registry/checkbox.json +1 -1
  58. package/registry/chip-link.json +1 -1
  59. package/registry/chip.json +1 -1
  60. package/registry/choice-grid.json +1 -1
  61. package/registry/code-block.json +1 -1
  62. package/registry/combobox.json +1 -1
  63. package/registry/command.json +1 -1
  64. package/registry/component-page.json +1 -1
  65. package/registry/confirm-button.json +1 -1
  66. package/registry/contact-page.json +1 -1
  67. package/registry/continue-prompt.json +1 -1
  68. package/registry/countdown.json +1 -1
  69. package/registry/cta-panel.json +1 -1
  70. package/registry/dashboard-layout.json +1 -1
  71. package/registry/data-table.json +1 -1
  72. package/registry/date-picker.json +2 -2
  73. package/registry/decision-list.json +1 -1
  74. package/registry/description-list.json +232 -0
  75. package/registry/detail-layout.json +1 -1
  76. package/registry/dialog.json +1 -1
  77. package/registry/docs-article-page.json +1 -1
  78. package/registry/docs-hub-page.json +1 -1
  79. package/registry/docs-layout.json +1 -1
  80. package/registry/dropdown-menu.json +1 -1
  81. package/registry/empty-state.json +1 -1
  82. package/registry/error-page.json +1 -1
  83. package/registry/examples/action-sheet/native/video-actions.d.ts +4 -0
  84. package/registry/examples/action-sheet/native/video-actions.dark.png +0 -0
  85. package/registry/examples/action-sheet/native/video-actions.js +30 -0
  86. package/registry/examples/action-sheet/native/video-actions.light.png +0 -0
  87. package/registry/examples/action-sheet/native/video-actions.tsx +24 -0
  88. package/registry/examples/activity-feed/job-activity.d.ts +4 -0
  89. package/registry/examples/activity-feed/job-activity.js +21 -0
  90. package/registry/examples/activity-feed/job-activity.tsx +17 -0
  91. package/registry/examples/activity-feed/live.d.ts +4 -0
  92. package/registry/examples/activity-feed/live.js +23 -0
  93. package/registry/examples/activity-feed/live.tsx +24 -0
  94. package/registry/examples/activity-feed/native/notifications.d.ts +4 -0
  95. package/registry/examples/activity-feed/native/notifications.dark.png +0 -0
  96. package/registry/examples/activity-feed/native/notifications.js +18 -0
  97. package/registry/examples/activity-feed/native/notifications.light.png +0 -0
  98. package/registry/examples/activity-feed/native/notifications.tsx +18 -0
  99. package/registry/examples/activity-feed/timeline.d.ts +4 -0
  100. package/registry/examples/activity-feed/timeline.js +25 -0
  101. package/registry/examples/activity-feed/timeline.tsx +19 -0
  102. package/registry/examples/avatar/native/presence.d.ts +4 -0
  103. package/registry/examples/avatar/native/presence.dark.png +0 -0
  104. package/registry/examples/avatar/native/presence.js +18 -0
  105. package/registry/examples/avatar/native/presence.light.png +0 -0
  106. package/registry/examples/avatar/native/presence.tsx +15 -0
  107. package/registry/examples/description-list/job-details.d.ts +4 -0
  108. package/registry/examples/description-list/job-details.js +23 -0
  109. package/registry/examples/description-list/job-details.tsx +17 -0
  110. package/registry/examples/description-list/key-value-grid.d.ts +4 -0
  111. package/registry/examples/description-list/key-value-grid.js +22 -0
  112. package/registry/examples/description-list/key-value-grid.tsx +16 -0
  113. package/registry/examples/description-list/native/job-details.d.ts +4 -0
  114. package/registry/examples/description-list/native/job-details.dark.png +0 -0
  115. package/registry/examples/description-list/native/job-details.js +33 -0
  116. package/registry/examples/description-list/native/job-details.light.png +0 -0
  117. package/registry/examples/description-list/native/job-details.tsx +24 -0
  118. package/registry/examples/description-list/receipt.d.ts +4 -0
  119. package/registry/examples/description-list/receipt.js +23 -0
  120. package/registry/examples/description-list/receipt.tsx +17 -0
  121. package/registry/examples/fab/native/extended.d.ts +4 -0
  122. package/registry/examples/fab/native/extended.dark.png +0 -0
  123. package/registry/examples/fab/native/extended.js +18 -0
  124. package/registry/examples/fab/native/extended.light.png +0 -0
  125. package/registry/examples/fab/native/extended.tsx +23 -0
  126. package/registry/examples/header/native/large-title.d.ts +4 -0
  127. package/registry/examples/header/native/large-title.dark.png +0 -0
  128. package/registry/examples/header/native/large-title.js +23 -0
  129. package/registry/examples/header/native/large-title.light.png +0 -0
  130. package/registry/examples/header/native/large-title.tsx +31 -0
  131. package/registry/examples/image-viewer/native/gallery.d.ts +4 -0
  132. package/registry/examples/image-viewer/native/gallery.dark.png +0 -0
  133. package/registry/examples/image-viewer/native/gallery.js +22 -0
  134. package/registry/examples/image-viewer/native/gallery.light.png +0 -0
  135. package/registry/examples/image-viewer/native/gallery.tsx +21 -0
  136. package/registry/examples/kanban/moderation.d.ts +4 -0
  137. package/registry/examples/kanban/moderation.js +35 -0
  138. package/registry/examples/kanban/moderation.tsx +37 -0
  139. package/registry/examples/list/jobs.d.ts +4 -0
  140. package/registry/examples/list/jobs.js +35 -0
  141. package/registry/examples/list/jobs.tsx +33 -0
  142. package/registry/examples/list/selectable.d.ts +4 -0
  143. package/registry/examples/list/selectable.js +33 -0
  144. package/registry/examples/list/selectable.tsx +30 -0
  145. package/registry/examples/list/virtualized.d.ts +4 -0
  146. package/registry/examples/list/virtualized.js +22 -0
  147. package/registry/examples/list/virtualized.tsx +17 -0
  148. package/registry/examples/loader/native/block.d.ts +4 -0
  149. package/registry/examples/loader/native/block.dark.png +0 -0
  150. package/registry/examples/loader/native/block.js +12 -0
  151. package/registry/examples/loader/native/block.light.png +0 -0
  152. package/registry/examples/loader/native/block.tsx +11 -0
  153. package/registry/examples/loader/native/job-wait.d.ts +4 -0
  154. package/registry/examples/loader/native/job-wait.dark.png +0 -0
  155. package/registry/examples/loader/native/job-wait.js +17 -0
  156. package/registry/examples/loader/native/job-wait.light.png +0 -0
  157. package/registry/examples/loader/native/job-wait.tsx +14 -0
  158. package/registry/examples/map/cluster.d.ts +4 -0
  159. package/registry/examples/map/cluster.js +16 -0
  160. package/registry/examples/map/cluster.tsx +18 -0
  161. package/registry/examples/map/location-picker.d.ts +4 -0
  162. package/registry/examples/map/location-picker.js +24 -0
  163. package/registry/examples/map/location-picker.tsx +22 -0
  164. package/registry/examples/map/native/location-picker.d.ts +4 -0
  165. package/registry/examples/map/native/location-picker.dark.png +0 -0
  166. package/registry/examples/map/native/location-picker.js +14 -0
  167. package/registry/examples/map/native/location-picker.light.png +0 -0
  168. package/registry/examples/map/native/location-picker.tsx +13 -0
  169. package/registry/examples/map/native/places.d.ts +4 -0
  170. package/registry/examples/map/native/places.dark.png +0 -0
  171. package/registry/examples/map/native/places.js +25 -0
  172. package/registry/examples/map/native/places.light.png +0 -0
  173. package/registry/examples/map/native/places.tsx +27 -0
  174. package/registry/examples/map/places.d.ts +4 -0
  175. package/registry/examples/map/places.js +28 -0
  176. package/registry/examples/map/places.tsx +28 -0
  177. package/registry/examples/map/static.d.ts +4 -0
  178. package/registry/examples/map/static.js +22 -0
  179. package/registry/examples/map/static.tsx +18 -0
  180. package/registry/examples/media-picker/native/story.d.ts +4 -0
  181. package/registry/examples/media-picker/native/story.dark.png +0 -0
  182. package/registry/examples/media-picker/native/story.js +30 -0
  183. package/registry/examples/media-picker/native/story.light.png +0 -0
  184. package/registry/examples/media-picker/native/story.tsx +26 -0
  185. package/registry/examples/meter/native/credits.d.ts +4 -0
  186. package/registry/examples/meter/native/credits.dark.png +0 -0
  187. package/registry/examples/meter/native/credits.js +15 -0
  188. package/registry/examples/meter/native/credits.light.png +0 -0
  189. package/registry/examples/meter/native/credits.tsx +12 -0
  190. package/registry/examples/meter/native/split-ring.d.ts +4 -0
  191. package/registry/examples/meter/native/split-ring.dark.png +0 -0
  192. package/registry/examples/meter/native/split-ring.js +24 -0
  193. package/registry/examples/meter/native/split-ring.light.png +0 -0
  194. package/registry/examples/meter/native/split-ring.tsx +19 -0
  195. package/registry/examples/number-ticker/native/balance.d.ts +4 -0
  196. package/registry/examples/number-ticker/native/balance.dark.png +0 -0
  197. package/registry/examples/number-ticker/native/balance.js +18 -0
  198. package/registry/examples/number-ticker/native/balance.light.png +0 -0
  199. package/registry/examples/number-ticker/native/balance.tsx +17 -0
  200. package/registry/examples/onboarding/native/first-launch.d.ts +4 -0
  201. package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
  202. package/registry/examples/onboarding/native/first-launch.js +23 -0
  203. package/registry/examples/onboarding/native/first-launch.light.png +0 -0
  204. package/registry/examples/onboarding/native/first-launch.tsx +19 -0
  205. package/registry/examples/otp-input/native/invalid.d.ts +4 -0
  206. package/registry/examples/otp-input/native/invalid.dark.png +0 -0
  207. package/registry/examples/otp-input/native/invalid.js +15 -0
  208. package/registry/examples/otp-input/native/invalid.light.png +0 -0
  209. package/registry/examples/otp-input/native/invalid.tsx +14 -0
  210. package/registry/examples/otp-input/native/verify.d.ts +4 -0
  211. package/registry/examples/otp-input/native/verify.dark.png +0 -0
  212. package/registry/examples/otp-input/native/verify.js +17 -0
  213. package/registry/examples/otp-input/native/verify.light.png +0 -0
  214. package/registry/examples/otp-input/native/verify.tsx +14 -0
  215. package/registry/examples/permission-prompt/native/blocked.d.ts +4 -0
  216. package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
  217. package/registry/examples/permission-prompt/native/blocked.js +25 -0
  218. package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
  219. package/registry/examples/permission-prompt/native/blocked.tsx +21 -0
  220. package/registry/examples/permission-prompt/native/camera.d.ts +4 -0
  221. package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
  222. package/registry/examples/permission-prompt/native/camera.js +25 -0
  223. package/registry/examples/permission-prompt/native/camera.light.png +0 -0
  224. package/registry/examples/permission-prompt/native/camera.tsx +21 -0
  225. package/registry/examples/pull-to-refresh/native/feed.d.ts +4 -0
  226. package/registry/examples/pull-to-refresh/native/feed.dark.png +0 -0
  227. package/registry/examples/pull-to-refresh/native/feed.js +14 -0
  228. package/registry/examples/pull-to-refresh/native/feed.light.png +0 -0
  229. package/registry/examples/pull-to-refresh/native/feed.tsx +19 -0
  230. package/registry/examples/search-field/native/cancel.d.ts +4 -0
  231. package/registry/examples/search-field/native/cancel.dark.png +0 -0
  232. package/registry/examples/search-field/native/cancel.js +14 -0
  233. package/registry/examples/search-field/native/cancel.light.png +0 -0
  234. package/registry/examples/search-field/native/cancel.tsx +13 -0
  235. package/registry/examples/stat/grid.d.ts +4 -0
  236. package/registry/examples/stat/grid.js +17 -0
  237. package/registry/examples/stat/grid.tsx +14 -0
  238. package/registry/examples/stepper/native/run.d.ts +4 -0
  239. package/registry/examples/stepper/native/run.dark.png +0 -0
  240. package/registry/examples/stepper/native/run.js +24 -0
  241. package/registry/examples/stepper/native/run.light.png +0 -0
  242. package/registry/examples/stepper/native/run.tsx +20 -0
  243. package/registry/examples/swipeable-row/native/conversation.d.ts +4 -0
  244. package/registry/examples/swipeable-row/native/conversation.dark.png +0 -0
  245. package/registry/examples/swipeable-row/native/conversation.js +30 -0
  246. package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
  247. package/registry/examples/swipeable-row/native/conversation.tsx +27 -0
  248. package/registry/examples/tab-bar/native/main-sections.d.ts +4 -0
  249. package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
  250. package/registry/examples/tab-bar/native/main-sections.js +29 -0
  251. package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
  252. package/registry/examples/tab-bar/native/main-sections.tsx +30 -0
  253. package/registry/examples/tabs/native/sections.d.ts +4 -0
  254. package/registry/examples/tabs/native/sections.dark.png +0 -0
  255. package/registry/examples/tabs/native/sections.js +23 -0
  256. package/registry/examples/tabs/native/sections.light.png +0 -0
  257. package/registry/examples/tabs/native/sections.tsx +19 -0
  258. package/registry/examples/tabs/native/segmented.d.ts +4 -0
  259. package/registry/examples/tabs/native/segmented.dark.png +0 -0
  260. package/registry/examples/tabs/native/segmented.js +22 -0
  261. package/registry/examples/tabs/native/segmented.light.png +0 -0
  262. package/registry/examples/tabs/native/segmented.tsx +18 -0
  263. package/registry/examples/toast/native/snackbar.d.ts +4 -0
  264. package/registry/examples/toast/native/snackbar.dark.png +0 -0
  265. package/registry/examples/toast/native/snackbar.js +23 -0
  266. package/registry/examples/toast/native/snackbar.light.png +0 -0
  267. package/registry/examples/toast/native/snackbar.tsx +21 -0
  268. package/registry/examples/tree-view/docs.d.ts +4 -0
  269. package/registry/examples/tree-view/docs.js +24 -0
  270. package/registry/examples/tree-view/docs.tsx +22 -0
  271. package/registry/examples/tree-view/lazy.d.ts +4 -0
  272. package/registry/examples/tree-view/lazy.js +21 -0
  273. package/registry/examples/tree-view/lazy.tsx +19 -0
  274. package/registry/fab.json +122 -0
  275. package/registry/field.json +1 -1
  276. package/registry/file-upload.json +2 -2
  277. package/registry/filter-bar.json +1 -1
  278. package/registry/form.json +2 -2
  279. package/registry/gallery-page.json +1 -1
  280. package/registry/glow-card.json +1 -1
  281. package/registry/goal-gauge.json +1 -1
  282. package/registry/header.json +137 -0
  283. package/registry/how-it-works-page.json +1 -1
  284. package/registry/image-cropper.json +1 -1
  285. package/registry/image-viewer.json +107 -0
  286. package/registry/index.json +299 -25
  287. package/registry/iso.json +1 -1
  288. package/registry/kanban.json +253 -0
  289. package/registry/kbd.json +1 -1
  290. package/registry/landing-page.json +1 -1
  291. package/registry/landscape.json +1 -1
  292. package/registry/legal-page.json +1 -1
  293. package/registry/link-card.json +1 -1
  294. package/registry/list.json +367 -30
  295. package/registry/loader.json +157 -4
  296. package/registry/longform-page.json +1 -1
  297. package/registry/map.json +1368 -0
  298. package/registry/marketing-layout.json +1 -1
  299. package/registry/marquee.json +1 -1
  300. package/registry/mascot-quote.json +1 -1
  301. package/registry/mascot-state.json +1 -1
  302. package/registry/mascots.json +1 -1
  303. package/registry/media-capture.json +1 -1
  304. package/registry/media-picker.json +129 -0
  305. package/registry/meter.json +136 -4
  306. package/registry/nav-bar.json +1 -1
  307. package/registry/number-ticker.json +96 -4
  308. package/registry/onboarding.json +95 -0
  309. package/registry/otp-input.json +150 -0
  310. package/registry/page-header.json +1 -1
  311. package/registry/page-hero.json +1 -1
  312. package/registry/page.json +1 -1
  313. package/registry/pagination.json +1 -1
  314. package/registry/permission-prompt.json +172 -0
  315. package/registry/pointer-light.json +1 -1
  316. package/registry/popover.json +1 -1
  317. package/registry/pricing-page.json +1 -1
  318. package/registry/product-page.json +1 -1
  319. package/registry/profile-card.json +1 -1
  320. package/registry/progress.json +2 -2
  321. package/registry/promise-card.json +1 -1
  322. package/registry/pull-to-refresh.json +74 -0
  323. package/registry/radio-group.json +1 -1
  324. package/registry/scroll-stage.json +1 -1
  325. package/registry/search-field.json +30 -3
  326. package/registry/section-backdrop.json +1 -1
  327. package/registry/separator.json +1 -1
  328. package/registry/settings-layout.json +1 -1
  329. package/registry/skeleton.json +1 -1
  330. package/registry/slider.json +1 -1
  331. package/registry/slot.json +1 -1
  332. package/registry/spinner.json +1 -1
  333. package/registry/split-view.json +1 -1
  334. package/registry/stage-banner.json +1 -1
  335. package/registry/stat.json +68 -5
  336. package/registry/status-page.json +1 -1
  337. package/registry/stepper.json +75 -4
  338. package/registry/swipeable-row.json +124 -0
  339. package/registry/switch.json +1 -1
  340. package/registry/tab-bar.json +115 -0
  341. package/registry/tabs.json +94 -4
  342. package/registry/tag-input.json +1 -1
  343. package/registry/terminal-replay.json +1 -1
  344. package/registry/theme.json +8 -1
  345. package/registry/toast.json +17 -3
  346. package/registry/toc.json +1 -1
  347. package/registry/tooltip.json +1 -1
  348. package/registry/tree-view.json +291 -0
  349. package/registry/video-player.json +1 -1
  350. package/registry/video-trimmer.json +1 -1
  351. package/registry/virtual.json +1 -1
  352. package/skills/map/SKILL.md +35 -0
@@ -0,0 +1,132 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const kanban: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ root?: tailwind_variants.ClassValue;
8
+ column?: tailwind_variants.ClassValue;
9
+ header?: tailwind_variants.ClassValue;
10
+ title?: tailwind_variants.ClassValue;
11
+ count?: tailwind_variants.ClassValue;
12
+ list?: tailwind_variants.ClassValue;
13
+ empty?: tailwind_variants.ClassValue;
14
+ card?: tailwind_variants.ClassValue;
15
+ };
16
+ };
17
+ } | {
18
+ [x: string]: {
19
+ [x: string]: tailwind_variants.ClassValue | {
20
+ root?: tailwind_variants.ClassValue;
21
+ column?: tailwind_variants.ClassValue;
22
+ header?: tailwind_variants.ClassValue;
23
+ title?: tailwind_variants.ClassValue;
24
+ count?: tailwind_variants.ClassValue;
25
+ list?: tailwind_variants.ClassValue;
26
+ empty?: tailwind_variants.ClassValue;
27
+ card?: tailwind_variants.ClassValue;
28
+ };
29
+ };
30
+ } | {}, {
31
+ root: string;
32
+ column: string;
33
+ header: string;
34
+ title: string;
35
+ count: string;
36
+ list: string;
37
+ card: string;
38
+ empty: string;
39
+ }, undefined, {
40
+ [key: string]: {
41
+ [key: string]: tailwind_variants.ClassValue | {
42
+ root?: tailwind_variants.ClassValue;
43
+ column?: tailwind_variants.ClassValue;
44
+ header?: tailwind_variants.ClassValue;
45
+ title?: tailwind_variants.ClassValue;
46
+ count?: tailwind_variants.ClassValue;
47
+ list?: tailwind_variants.ClassValue;
48
+ empty?: tailwind_variants.ClassValue;
49
+ card?: tailwind_variants.ClassValue;
50
+ };
51
+ };
52
+ } | {}, {
53
+ root: string;
54
+ column: string;
55
+ header: string;
56
+ title: string;
57
+ count: string;
58
+ list: string;
59
+ card: string;
60
+ empty: string;
61
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
62
+ root: string;
63
+ column: string;
64
+ header: string;
65
+ title: string;
66
+ count: string;
67
+ list: string;
68
+ card: string;
69
+ empty: string;
70
+ }>>;
71
+ type KanbanColumn = {
72
+ /** A stable id. */
73
+ id: string;
74
+ /** Its name — passed translated (“To review”). */
75
+ title: string;
76
+ /** The most cards it should hold: the count turns to danger past it. */
77
+ limit?: number;
78
+ };
79
+ type KanbanMove = {
80
+ /** The card moved. */
81
+ cardId: string;
82
+ /** Where it came from. */
83
+ from: string;
84
+ /** The column it went to. */
85
+ to: string;
86
+ /** Its position in that column (0 = top). */
87
+ index: number;
88
+ };
89
+ type KanbanLabels = {
90
+ /** The hint read on a card: how to move it with the keyboard. */
91
+ instructions: string;
92
+ /** Announced when a card is picked up: `(card, column) => …`. */
93
+ grabbed: (card: string, column: string) => string;
94
+ /** Announced as it moves: `(card, column, position, total) => …`. */
95
+ moved: (card: string, column: string, position: number, total: number) => string;
96
+ /** Announced when it is dropped. */
97
+ dropped: (card: string, column: string, position: number) => string;
98
+ /** Announced when the move is cancelled. */
99
+ cancelled: (card: string) => string;
100
+ /** A column without card (“No card”). */
101
+ empty: string;
102
+ };
103
+ declare const kanbanLabels: KanbanLabels;
104
+ type KanbanProps<T> = {
105
+ /** The columns, in order. */
106
+ columns: readonly KanbanColumn[];
107
+ /** The cards, in their order within each column. */
108
+ cards: readonly T[];
109
+ /** A card's id. */
110
+ getId: (card: T) => string;
111
+ /** A card's column. */
112
+ getColumn: (card: T) => string;
113
+ /** A card's name, for the announcements. */
114
+ getTitle: (card: T) => string;
115
+ /** What a card shows. */
116
+ renderCard: (card: T) => React.ReactNode;
117
+ /** Called when a card is dropped somewhere new: update the data here. */
118
+ onMove: (move: KanbanMove) => void;
119
+ /** The board's accessible name (“Moderation queue”). */
120
+ "aria-label": string;
121
+ /** The words, passed translated; English by default. */
122
+ labels?: Partial<KanbanLabels>;
123
+ /** Classes merged on the root. */
124
+ className?: string;
125
+ };
126
+ /**
127
+ * A board of cards in columns — a moderation queue, a release plan: drag and drop with the pointer, or Space and the
128
+ * arrow keys, every step announced. Column limits show in the counts.
129
+ */
130
+ declare function Kanban<T>({ columns, cards, getId, getColumn, getTitle, renderCard, onMove, "aria-label": label, labels: words, className }: KanbanProps<T>): React.JSX.Element;
131
+
132
+ export { Kanban, type KanbanColumn, type KanbanLabels, type KanbanMove, type KanbanProps, kanban, kanbanLabels };
package/dist/kanban.js ADDED
@@ -0,0 +1,187 @@
1
+ "use client";
2
+
3
+ // src/kanban/kanban.tsx
4
+ import * as React from "react";
5
+ import { tv } from "tailwind-variants";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ var kanban = tv({
8
+ slots: {
9
+ root: "flex w-full gap-3 overflow-x-auto pb-2",
10
+ column: "flex w-72 shrink-0 flex-col rounded-xl border border-border-default bg-surface-1 data-[over]:border-accent data-[over]:bg-accent-soft/40",
11
+ header: "flex items-center gap-2 px-3 pb-2 pt-3",
12
+ title: "min-w-0 flex-1 truncate text-sm font-semibold text-fg",
13
+ count: "rounded-full bg-surface-3 px-2 text-xs font-semibold tabular-nums text-fg-secondary data-[over-limit]:bg-danger data-[over-limit]:text-on-accent",
14
+ list: "m-0 flex min-h-16 list-none flex-col gap-2 p-2 pt-0",
15
+ card: "cursor-grab rounded-lg border border-border-default bg-surface-0 p-3 text-sm text-fg shadow-xs outline-hidden transition-shadow focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing data-[grabbed]:ring-2 data-[grabbed]:ring-accent data-[grabbed]:shadow-lg data-[dragging]:opacity-40",
16
+ empty: "rounded-lg border border-dashed border-border-default px-3 py-4 text-center text-xs text-fg-secondary"
17
+ }
18
+ });
19
+ var kanbanLabels = {
20
+ instructions: "Press Space to pick it up, the arrow keys to move it, Space to drop it, Escape to cancel.",
21
+ grabbed: (card, column) => `${card} picked up, in ${column}.`,
22
+ moved: (card, column, position, total) => `${card}: ${column}, position ${position} of ${total}.`,
23
+ dropped: (card, column, position) => `${card} dropped in ${column}, position ${position}.`,
24
+ cancelled: (card) => `Move of ${card} cancelled.`,
25
+ empty: "No card"
26
+ };
27
+ function Kanban({ columns, cards, getId, getColumn, getTitle, renderCard, onMove, "aria-label": label, labels: words, className }) {
28
+ const labels = { ...kanbanLabels, ...words };
29
+ const s = kanban();
30
+ const instructionsId = React.useId();
31
+ const [grab, setGrab] = React.useState(null);
32
+ const [dragging, setDragging] = React.useState(null);
33
+ const [over, setOver] = React.useState(null);
34
+ const [message, setMessage] = React.useState("");
35
+ const refs = React.useRef(/* @__PURE__ */ new Map());
36
+ const byColumn = (column, without) => cards.filter((c) => getColumn(c) === column && getId(c) !== without);
37
+ const titleOf = (id) => {
38
+ const card = cards.find((c) => getId(c) === id);
39
+ return card ? getTitle(card) : id;
40
+ };
41
+ const columnTitle = (id) => columns.find((c) => c.id === id)?.title ?? id;
42
+ const placementOf = (id) => {
43
+ const card = cards.find((c) => getId(c) === id);
44
+ const column = getColumn(card);
45
+ return { column, index: byColumn(column).findIndex((c) => getId(c) === id) };
46
+ };
47
+ const commit = (id, from, to) => {
48
+ if (from.column !== to.column || from.index !== to.index) onMove({ cardId: id, from: from.column, to: to.column, index: to.index });
49
+ };
50
+ const shown = (column) => {
51
+ const list = byColumn(column, grab?.id);
52
+ if (grab && grab.at.column === column) {
53
+ const card = cards.find((c) => getId(c) === grab.id);
54
+ if (card) list.splice(grab.at.index, 0, card);
55
+ }
56
+ return list;
57
+ };
58
+ React.useEffect(() => {
59
+ if (grab) refs.current.get(grab.id)?.focus();
60
+ }, [grab]);
61
+ const onKeyDown = (event, id) => {
62
+ const title = titleOf(id);
63
+ if (!grab) {
64
+ if (event.key === " " || event.key === "Enter") {
65
+ event.preventDefault();
66
+ const origin2 = placementOf(id);
67
+ setGrab({ id, origin: origin2, at: origin2 });
68
+ setMessage(labels.grabbed(title, columnTitle(origin2.column)));
69
+ }
70
+ return;
71
+ }
72
+ const { at, origin } = grab;
73
+ const columnIndex = columns.findIndex((c) => c.id === at.column);
74
+ let next = null;
75
+ if (event.key === "ArrowLeft" && columnIndex > 0) next = { column: columns[columnIndex - 1].id, index: Math.min(at.index, byColumn(columns[columnIndex - 1].id, id).length) };
76
+ if (event.key === "ArrowRight" && columnIndex < columns.length - 1) next = { column: columns[columnIndex + 1].id, index: Math.min(at.index, byColumn(columns[columnIndex + 1].id, id).length) };
77
+ if (event.key === "ArrowUp" && at.index > 0) next = { ...at, index: at.index - 1 };
78
+ if (event.key === "ArrowDown" && at.index < byColumn(at.column, id).length) next = { ...at, index: at.index + 1 };
79
+ if (next) {
80
+ event.preventDefault();
81
+ setGrab({ ...grab, at: next });
82
+ setMessage(labels.moved(title, columnTitle(next.column), next.index + 1, byColumn(next.column, id).length + 1));
83
+ return;
84
+ }
85
+ if (event.key === " " || event.key === "Enter") {
86
+ event.preventDefault();
87
+ setGrab(null);
88
+ commit(id, origin, at);
89
+ setMessage(labels.dropped(title, columnTitle(at.column), at.index + 1));
90
+ } else if (event.key === "Escape") {
91
+ event.preventDefault();
92
+ setGrab(null);
93
+ setMessage(labels.cancelled(title));
94
+ }
95
+ };
96
+ const indexAt = (column, y) => {
97
+ const list = byColumn(column, dragging ?? void 0);
98
+ const i = list.findIndex((c) => {
99
+ const box = refs.current.get(getId(c))?.getBoundingClientRect();
100
+ return box ? y < box.top + box.height / 2 : false;
101
+ });
102
+ return i === -1 ? list.length : i;
103
+ };
104
+ return /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": label, className: s.root({ className }), children: [
105
+ /* @__PURE__ */ jsx("p", { id: instructionsId, className: "sr-only", children: labels.instructions }),
106
+ /* @__PURE__ */ jsx("p", { className: "sr-only", "aria-live": "assertive", children: message }),
107
+ columns.map((column) => {
108
+ const list = shown(column.id);
109
+ const overLimit = column.limit !== void 0 && list.length > column.limit;
110
+ return /* @__PURE__ */ jsxs(
111
+ "section",
112
+ {
113
+ "aria-label": column.title,
114
+ "data-over": over?.column === column.id || void 0,
115
+ className: s.column(),
116
+ onDragOver: (e) => {
117
+ if (!dragging) return;
118
+ e.preventDefault();
119
+ setOver({ column: column.id, index: indexAt(column.id, e.clientY) });
120
+ },
121
+ onDragLeave: (e) => {
122
+ if (!e.currentTarget.contains(e.relatedTarget)) setOver(null);
123
+ },
124
+ onDrop: (e) => {
125
+ e.preventDefault();
126
+ if (dragging) commit(dragging, placementOf(dragging), { column: column.id, index: indexAt(column.id, e.clientY) });
127
+ setDragging(null);
128
+ setOver(null);
129
+ },
130
+ children: [
131
+ /* @__PURE__ */ jsxs("header", { className: s.header(), children: [
132
+ /* @__PURE__ */ jsx("h3", { className: s.title(), children: column.title }),
133
+ /* @__PURE__ */ jsx("span", { className: s.count(), "data-over-limit": overLimit || void 0, children: column.limit !== void 0 ? `${list.length}/${column.limit}` : list.length })
134
+ ] }),
135
+ /* @__PURE__ */ jsxs("ul", { className: s.list(), children: [
136
+ list.length === 0 ? /* @__PURE__ */ jsx("li", { className: s.empty(), children: labels.empty }) : null,
137
+ list.map((card) => {
138
+ const id = getId(card);
139
+ return /* @__PURE__ */ jsx(
140
+ "li",
141
+ {
142
+ ref: (el) => {
143
+ if (el) refs.current.set(id, el);
144
+ else refs.current.delete(id);
145
+ },
146
+ tabIndex: 0,
147
+ draggable: true,
148
+ "aria-describedby": instructionsId,
149
+ "aria-roledescription": "card",
150
+ "data-grabbed": grab?.id === id || void 0,
151
+ "data-dragging": dragging === id || void 0,
152
+ className: s.card(),
153
+ onKeyDown: (e) => onKeyDown(e, id),
154
+ onFocus: () => {
155
+ if (grab && grab.id !== id) {
156
+ setMessage(labels.cancelled(titleOf(grab.id)));
157
+ setGrab(null);
158
+ }
159
+ },
160
+ onDragStart: (e) => {
161
+ e.dataTransfer.effectAllowed = "move";
162
+ e.dataTransfer.setData("text/plain", id);
163
+ setDragging(id);
164
+ },
165
+ onDragEnd: () => {
166
+ setDragging(null);
167
+ setOver(null);
168
+ },
169
+ children: renderCard(card)
170
+ },
171
+ id
172
+ );
173
+ })
174
+ ] })
175
+ ]
176
+ },
177
+ column.id
178
+ );
179
+ })
180
+ ] });
181
+ }
182
+ export {
183
+ Kanban,
184
+ kanban,
185
+ kanbanLabels
186
+ };
187
+ //# sourceMappingURL=kanban.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kanban/kanban.tsx"],"sourcesContent":["// Client (the drag, the keyboard move, the announcements). Cards in columns that move by drag and drop — and by the\n// keyboard: Space picks a card up, the arrows carry it (← → between columns, ↑ ↓ within one), Space drops it, Esc puts it\n// back. Every move is announced in words. The app owns the data: `onMove` says where a card went.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const kanban = tv({\n slots: {\n root: \"flex w-full gap-3 overflow-x-auto pb-2\",\n column: \"flex w-72 shrink-0 flex-col rounded-xl border border-border-default bg-surface-1 data-[over]:border-accent data-[over]:bg-accent-soft/40\",\n header: \"flex items-center gap-2 px-3 pb-2 pt-3\",\n title: \"min-w-0 flex-1 truncate text-sm font-semibold text-fg\",\n count: \"rounded-full bg-surface-3 px-2 text-xs font-semibold tabular-nums text-fg-secondary data-[over-limit]:bg-danger data-[over-limit]:text-on-accent\",\n list: \"m-0 flex min-h-16 list-none flex-col gap-2 p-2 pt-0\",\n card:\n \"cursor-grab rounded-lg border border-border-default bg-surface-0 p-3 text-sm text-fg shadow-xs outline-hidden transition-shadow \" +\n \"focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing data-[grabbed]:ring-2 data-[grabbed]:ring-accent data-[grabbed]:shadow-lg data-[dragging]:opacity-40\",\n empty: \"rounded-lg border border-dashed border-border-default px-3 py-4 text-center text-xs text-fg-secondary\",\n },\n});\n\nexport type KanbanColumn = {\n /** A stable id. */\n id: string;\n /** Its name — passed translated (“To review”). */\n title: string;\n /** The most cards it should hold: the count turns to danger past it. */\n limit?: number;\n};\n\nexport type KanbanMove = {\n /** The card moved. */\n cardId: string;\n /** Where it came from. */\n from: string;\n /** The column it went to. */\n to: string;\n /** Its position in that column (0 = top). */\n index: number;\n};\n\nexport type KanbanLabels = {\n /** The hint read on a card: how to move it with the keyboard. */\n instructions: string;\n /** Announced when a card is picked up: `(card, column) => …`. */\n grabbed: (card: string, column: string) => string;\n /** Announced as it moves: `(card, column, position, total) => …`. */\n moved: (card: string, column: string, position: number, total: number) => string;\n /** Announced when it is dropped. */\n dropped: (card: string, column: string, position: number) => string;\n /** Announced when the move is cancelled. */\n cancelled: (card: string) => string;\n /** A column without card (“No card”). */\n empty: string;\n};\n\nexport const kanbanLabels: KanbanLabels = {\n instructions: \"Press Space to pick it up, the arrow keys to move it, Space to drop it, Escape to cancel.\",\n grabbed: (card, column) => `${card} picked up, in ${column}.`,\n moved: (card, column, position, total) => `${card}: ${column}, position ${position} of ${total}.`,\n dropped: (card, column, position) => `${card} dropped in ${column}, position ${position}.`,\n cancelled: (card) => `Move of ${card} cancelled.`,\n empty: \"No card\",\n};\n\nexport type KanbanProps<T> = {\n /** The columns, in order. */\n columns: readonly KanbanColumn[];\n /** The cards, in their order within each column. */\n cards: readonly T[];\n /** A card's id. */\n getId: (card: T) => string;\n /** A card's column. */\n getColumn: (card: T) => string;\n /** A card's name, for the announcements. */\n getTitle: (card: T) => string;\n /** What a card shows. */\n renderCard: (card: T) => React.ReactNode;\n /** Called when a card is dropped somewhere new: update the data here. */\n onMove: (move: KanbanMove) => void;\n /** The board's accessible name (“Moderation queue”). */\n \"aria-label\": string;\n /** The words, passed translated; English by default. */\n labels?: Partial<KanbanLabels>;\n /** Classes merged on the root. */\n className?: string;\n};\n\ntype Placement = { column: string; index: number };\n\n/**\n * A board of cards in columns — a moderation queue, a release plan: drag and drop with the pointer, or Space and the\n * arrow keys, every step announced. Column limits show in the counts.\n */\nexport function Kanban<T>({ columns, cards, getId, getColumn, getTitle, renderCard, onMove, \"aria-label\": label, labels: words, className }: KanbanProps<T>) {\n const labels = { ...kanbanLabels, ...words };\n const s = kanban();\n const instructionsId = React.useId();\n const [grab, setGrab] = React.useState<{ id: string; origin: Placement; at: Placement } | null>(null);\n const [dragging, setDragging] = React.useState<string | null>(null);\n const [over, setOver] = React.useState<Placement | null>(null);\n const [message, setMessage] = React.useState(\"\");\n const refs = React.useRef(new Map<string, HTMLLIElement>());\n const byColumn = (column: string, without?: string) => cards.filter((c) => getColumn(c) === column && getId(c) !== without);\n const titleOf = (id: string) => {\n const card = cards.find((c) => getId(c) === id);\n return card ? getTitle(card) : id;\n };\n const columnTitle = (id: string) => columns.find((c) => c.id === id)?.title ?? id;\n const placementOf = (id: string): Placement => {\n const card = cards.find((c) => getId(c) === id)!;\n const column = getColumn(card);\n return { column, index: byColumn(column).findIndex((c) => getId(c) === id) };\n };\n const commit = (id: string, from: Placement, to: Placement) => {\n if (from.column !== to.column || from.index !== to.index) onMove({ cardId: id, from: from.column, to: to.column, index: to.index });\n };\n // The cards of a column as shown, with the grabbed card at its keyboard position.\n const shown = (column: string) => {\n const list = byColumn(column, grab?.id);\n if (grab && grab.at.column === column) {\n const card = cards.find((c) => getId(c) === grab.id);\n if (card) list.splice(grab.at.index, 0, card);\n }\n return list;\n };\n React.useEffect(() => {\n if (grab) refs.current.get(grab.id)?.focus();\n }, [grab]);\n\n const onKeyDown = (event: React.KeyboardEvent, id: string) => {\n const title = titleOf(id);\n if (!grab) {\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n const origin = placementOf(id);\n setGrab({ id, origin, at: origin });\n setMessage(labels.grabbed(title, columnTitle(origin.column)));\n }\n return;\n }\n const { at, origin } = grab;\n const columnIndex = columns.findIndex((c) => c.id === at.column);\n let next: Placement | null = null;\n if (event.key === \"ArrowLeft\" && columnIndex > 0) next = { column: columns[columnIndex - 1]!.id, index: Math.min(at.index, byColumn(columns[columnIndex - 1]!.id, id).length) };\n if (event.key === \"ArrowRight\" && columnIndex < columns.length - 1) next = { column: columns[columnIndex + 1]!.id, index: Math.min(at.index, byColumn(columns[columnIndex + 1]!.id, id).length) };\n if (event.key === \"ArrowUp\" && at.index > 0) next = { ...at, index: at.index - 1 };\n if (event.key === \"ArrowDown\" && at.index < byColumn(at.column, id).length) next = { ...at, index: at.index + 1 };\n if (next) {\n event.preventDefault();\n setGrab({ ...grab, at: next });\n setMessage(labels.moved(title, columnTitle(next.column), next.index + 1, byColumn(next.column, id).length + 1));\n return;\n }\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n setGrab(null);\n commit(id, origin, at);\n setMessage(labels.dropped(title, columnTitle(at.column), at.index + 1));\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n setGrab(null);\n setMessage(labels.cancelled(title));\n }\n };\n\n const indexAt = (column: string, y: number) => {\n const list = byColumn(column, dragging ?? undefined);\n const i = list.findIndex((c) => {\n const box = refs.current.get(getId(c))?.getBoundingClientRect();\n return box ? y < box.top + box.height / 2 : false;\n });\n return i === -1 ? list.length : i;\n };\n\n return (\n <div role=\"group\" aria-label={label} className={s.root({ className })}>\n <p id={instructionsId} className=\"sr-only\">\n {labels.instructions}\n </p>\n <p className=\"sr-only\" aria-live=\"assertive\">\n {message}\n </p>\n {columns.map((column) => {\n const list = shown(column.id);\n const overLimit = column.limit !== undefined && list.length > column.limit;\n return (\n <section\n key={column.id}\n aria-label={column.title}\n data-over={over?.column === column.id || undefined}\n className={s.column()}\n onDragOver={(e) => {\n if (!dragging) return;\n e.preventDefault();\n setOver({ column: column.id, index: indexAt(column.id, e.clientY) });\n }}\n onDragLeave={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setOver(null);\n }}\n onDrop={(e) => {\n e.preventDefault();\n if (dragging) commit(dragging, placementOf(dragging), { column: column.id, index: indexAt(column.id, e.clientY) });\n setDragging(null);\n setOver(null);\n }}\n >\n <header className={s.header()}>\n <h3 className={s.title()}>{column.title}</h3>\n <span className={s.count()} data-over-limit={overLimit || undefined}>\n {column.limit !== undefined ? `${list.length}/${column.limit}` : list.length}\n </span>\n </header>\n <ul className={s.list()}>\n {list.length === 0 ? <li className={s.empty()}>{labels.empty}</li> : null}\n {list.map((card) => {\n const id = getId(card);\n return (\n <li\n key={id}\n ref={(el) => {\n if (el) refs.current.set(id, el);\n else refs.current.delete(id);\n }}\n tabIndex={0}\n draggable\n aria-describedby={instructionsId}\n aria-roledescription=\"card\"\n data-grabbed={grab?.id === id || undefined}\n data-dragging={dragging === id || undefined}\n className={s.card()}\n onKeyDown={(e) => onKeyDown(e, id)}\n onFocus={() => {\n // Tab to another card while one is carried: the carried one goes back.\n if (grab && grab.id !== id) {\n setMessage(labels.cancelled(titleOf(grab.id)));\n setGrab(null);\n }\n }}\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", id);\n setDragging(id);\n }}\n onDragEnd={() => {\n setDragging(null);\n setOver(null);\n }}\n >\n {renderCard(card)}\n </li>\n );\n })}\n </ul>\n </section>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["origin"]}
package/dist/list.d.ts ADDED
@@ -0,0 +1,153 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const list: tailwind_variants.TVReturnType<{
5
+ density: {
6
+ comfortable: {
7
+ item: string;
8
+ };
9
+ compact: {
10
+ item: string;
11
+ description: string;
12
+ };
13
+ };
14
+ }, {
15
+ root: string;
16
+ scroller: string;
17
+ ul: string;
18
+ item: string;
19
+ main: string;
20
+ leading: string;
21
+ text: string;
22
+ title: string;
23
+ description: string;
24
+ meta: string;
25
+ actions: string;
26
+ chevron: string;
27
+ message: string;
28
+ skeleton: string;
29
+ footer: string;
30
+ }, undefined, {
31
+ density: {
32
+ comfortable: {
33
+ item: string;
34
+ };
35
+ compact: {
36
+ item: string;
37
+ description: string;
38
+ };
39
+ };
40
+ }, {
41
+ root: string;
42
+ scroller: string;
43
+ ul: string;
44
+ item: string;
45
+ main: string;
46
+ leading: string;
47
+ text: string;
48
+ title: string;
49
+ description: string;
50
+ meta: string;
51
+ actions: string;
52
+ chevron: string;
53
+ message: string;
54
+ skeleton: string;
55
+ footer: string;
56
+ }, tailwind_variants.TVReturnTypeLike<{
57
+ density: {
58
+ comfortable: {
59
+ item: string;
60
+ };
61
+ compact: {
62
+ item: string;
63
+ description: string;
64
+ };
65
+ };
66
+ }, {
67
+ root: string;
68
+ scroller: string;
69
+ ul: string;
70
+ item: string;
71
+ main: string;
72
+ leading: string;
73
+ text: string;
74
+ title: string;
75
+ description: string;
76
+ meta: string;
77
+ actions: string;
78
+ chevron: string;
79
+ message: string;
80
+ skeleton: string;
81
+ footer: string;
82
+ }>>;
83
+ type ListLabels = {
84
+ /** The checkbox of a row: `(title) => "Select " + title`. */
85
+ selectRow: (title: string) => string;
86
+ /** Read while the rows load (“Loading”). */
87
+ loading: string;
88
+ /** The default empty state (“Nothing to show”). */
89
+ empty: string;
90
+ };
91
+ declare const listLabels: ListLabels;
92
+ type ListRow = {
93
+ /** The row's main line — passed translated. */
94
+ title: string;
95
+ /** A second line (a detail, a status in words). */
96
+ description?: React.ReactNode;
97
+ /** Before the text: an `Avatar`, an icon, a thumbnail. */
98
+ leading?: React.ReactNode;
99
+ /** After the text: a time, an amount, a `Badge`. */
100
+ meta?: React.ReactNode;
101
+ /** Secondary actions beside the row (icon buttons, a menu) — outside the main action. */
102
+ actions?: React.ReactNode;
103
+ /** The row opens this address (its main action is a link). */
104
+ href?: string;
105
+ /** The row's main action (a button), when it is not a link. */
106
+ onSelect?: () => void;
107
+ };
108
+ type ListProps<T> = {
109
+ /** The records, in order. */
110
+ items: readonly T[];
111
+ /** A stable id per record: the React key and the selection's value. */
112
+ getId: (item: T) => string;
113
+ /** What a record shows: its title, line, visuals, details, actions and where it leads. */
114
+ row: (item: T) => ListRow;
115
+ /** The list's accessible name (“Jobs”). */
116
+ "aria-label": string;
117
+ /** comfortable (default: 64 px rows with a line) · compact (44 px: dense admin lists). */
118
+ density?: "comfortable" | "compact";
119
+ /** A checkbox per row. */
120
+ selectable?: boolean;
121
+ /** The ids selected (controlled). */
122
+ selected?: readonly string[];
123
+ /** The ids selected at first, uncontrolled. */
124
+ defaultSelected?: readonly string[];
125
+ /** Called with the new selection. */
126
+ onSelectedChange?: (selected: string[]) => void;
127
+ /** Shows a chevron on the rows that lead somewhere. */
128
+ chevrons?: boolean;
129
+ /** Loading: `loadingRows` skeleton rows and `aria-busy`. */
130
+ loading?: boolean;
131
+ /** How many skeleton rows. Default 5. */
132
+ loadingRows?: number;
133
+ /** A failure in place of the rows (an `Alert` with a retry); announced. */
134
+ error?: React.ReactNode;
135
+ /** Shown when there is no record (an `EmptyState`). */
136
+ empty?: React.ReactNode;
137
+ /** Renders only the rows in view: fixed `rowHeight`, a scrolling region of `height` px. */
138
+ virtualize?: {
139
+ rowHeight: number;
140
+ height: number;
141
+ overscan?: number;
142
+ };
143
+ /** Under the list: a `Pagination`, a “Load more” button, a total. */
144
+ footer?: React.ReactNode;
145
+ /** The words, passed translated; English by default. */
146
+ labels?: Partial<ListLabels>;
147
+ /** Classes merged on the root. */
148
+ className?: string;
149
+ };
150
+ /** A list of records: dense or comfortable, selectable, actions beside each row, windowed when long, with its states. */
151
+ declare function List<T>({ items, getId, row, "aria-label": label, density, selectable, selected: selectedProp, defaultSelected, onSelectedChange, chevrons, loading, loadingRows, error, empty, virtualize, footer, labels: given, className, }: ListProps<T>): React.JSX.Element;
152
+
153
+ export { List, type ListLabels, type ListProps, type ListRow, list, listLabels };
package/dist/list.js ADDED
@@ -0,0 +1,130 @@
1
+ "use client";
2
+ import {
3
+ Checkbox
4
+ } from "./chunk-7Z4KHPFC.js";
5
+ import {
6
+ useControllable
7
+ } from "./chunk-BRKMQ6JV.js";
8
+ import {
9
+ ChevronGlyph
10
+ } from "./chunk-CPA5CF35.js";
11
+
12
+ // src/list/list.tsx
13
+ import * as React from "react";
14
+ import { tv } from "tailwind-variants";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
+ var list = tv({
17
+ slots: {
18
+ root: "w-full overflow-hidden rounded-xl border border-border-default bg-surface-1",
19
+ scroller: "overflow-y-auto focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
20
+ ul: "m-0 list-none divide-y divide-border-subtle p-0",
21
+ item: "relative flex items-center gap-3 px-4 transition-colors data-[state=selected]:bg-accent-soft has-[[data-main]:hover]:bg-surface-2/60",
22
+ main: "flex min-w-0 flex-1 items-center gap-3 self-stretch text-left text-fg outline-hidden focus-visible:after:absolute focus-visible:after:inset-0.5 focus-visible:after:rounded-lg focus-visible:after:ring-2 focus-visible:after:ring-ring",
23
+ leading: "flex shrink-0 items-center justify-center text-fg-secondary",
24
+ text: "flex min-w-0 flex-1 flex-col",
25
+ title: "truncate text-sm font-semibold text-fg",
26
+ description: "line-clamp-2 text-xs text-fg-secondary",
27
+ meta: "flex shrink-0 flex-col items-end gap-1 text-xs tabular-nums text-fg-secondary",
28
+ actions: "relative z-10 flex shrink-0 items-center gap-1",
29
+ chevron: "h-4 w-4 shrink-0 text-fg-muted",
30
+ message: "px-4 py-10 text-center text-sm text-fg-secondary",
31
+ skeleton: "animate-pulse rounded bg-surface-3 motion-reduce:animate-none",
32
+ footer: "border-t border-border-default px-4 py-3"
33
+ },
34
+ variants: {
35
+ density: {
36
+ comfortable: { item: "min-h-16 py-2.5" },
37
+ compact: { item: "min-h-11 py-1.5", description: "line-clamp-1" }
38
+ }
39
+ },
40
+ defaultVariants: { density: "comfortable" }
41
+ });
42
+ var listLabels = { selectRow: (title) => `Select ${title}`, loading: "Loading", empty: "Nothing to show" };
43
+ function List({
44
+ items,
45
+ getId,
46
+ row,
47
+ "aria-label": label,
48
+ density,
49
+ selectable,
50
+ selected: selectedProp,
51
+ defaultSelected = [],
52
+ onSelectedChange,
53
+ chevrons,
54
+ loading,
55
+ loadingRows = 5,
56
+ error,
57
+ empty,
58
+ virtualize,
59
+ footer,
60
+ labels: given,
61
+ className
62
+ }) {
63
+ const labels = { ...listLabels, ...given };
64
+ const s = list({ density });
65
+ const [selected, setSelected] = useControllable(selectedProp, defaultSelected, onSelectedChange);
66
+ const [scrollTop, setScrollTop] = React.useState(0);
67
+ const chosen = new Set(selected);
68
+ const toggle = (id) => setSelected(chosen.has(id) ? selected.filter((x) => x !== id) : [...selected, id]);
69
+ let shown = items;
70
+ let before = 0;
71
+ let after = 0;
72
+ if (virtualize && !loading) {
73
+ const overscan = virtualize.overscan ?? 6;
74
+ const start = Math.max(0, Math.floor(scrollTop / virtualize.rowHeight) - overscan);
75
+ const end = Math.min(items.length, Math.ceil((scrollTop + virtualize.height) / virtualize.rowHeight) + overscan);
76
+ shown = items.slice(start, end);
77
+ before = start * virtualize.rowHeight;
78
+ after = (items.length - end) * virtualize.rowHeight;
79
+ }
80
+ let body;
81
+ if (loading) {
82
+ body = Array.from({ length: loadingRows }, (_, i) => /* @__PURE__ */ jsxs("li", { "aria-hidden": true, className: s.item(), children: [
83
+ /* @__PURE__ */ jsx("div", { className: s.skeleton({ className: "h-9 w-9 rounded-full" }) }),
84
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-2", children: [
85
+ /* @__PURE__ */ jsx("div", { className: s.skeleton({ className: "h-3.5 w-2/5" }) }),
86
+ /* @__PURE__ */ jsx("div", { className: s.skeleton({ className: "h-3 w-3/5" }) })
87
+ ] })
88
+ ] }, `loading-${i}`));
89
+ } else if (error) {
90
+ body = /* @__PURE__ */ jsx("li", { className: s.message(), children: /* @__PURE__ */ jsx("div", { role: "alert", children: error }) });
91
+ } else if (items.length === 0) {
92
+ body = /* @__PURE__ */ jsx("li", { className: s.message(), children: empty ?? labels.empty });
93
+ } else {
94
+ body = shown.map((item) => {
95
+ const id = getId(item);
96
+ const r = row(item);
97
+ const isChosen = chosen.has(id);
98
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
99
+ r.leading ? /* @__PURE__ */ jsx("span", { className: s.leading(), children: r.leading }) : null,
100
+ /* @__PURE__ */ jsxs("span", { className: s.text(), children: [
101
+ /* @__PURE__ */ jsx("span", { className: s.title(), children: r.title }),
102
+ r.description ? /* @__PURE__ */ jsx("span", { className: s.description(), children: r.description }) : null
103
+ ] }),
104
+ r.meta ? /* @__PURE__ */ jsx("span", { className: s.meta(), children: r.meta }) : null,
105
+ chevrons && (r.href || r.onSelect) ? /* @__PURE__ */ jsx(ChevronGlyph, { direction: "right", className: s.chevron() }) : null
106
+ ] });
107
+ return /* @__PURE__ */ jsxs("li", { "data-state": isChosen ? "selected" : void 0, className: s.item(), style: virtualize ? { height: virtualize.rowHeight } : void 0, children: [
108
+ selectable ? /* @__PURE__ */ jsx(Checkbox, { checked: isChosen, onCheckedChange: () => toggle(id), "aria-label": labels.selectRow(r.title), className: "relative z-10" }) : null,
109
+ r.href ? /* @__PURE__ */ jsx("a", { href: r.href, "data-main": "", className: s.main(), children: content }) : r.onSelect ? /* @__PURE__ */ jsx("button", { type: "button", "data-main": "", onClick: r.onSelect, className: s.main(), children: content }) : /* @__PURE__ */ jsx("div", { className: s.main(), children: content }),
110
+ r.actions ? /* @__PURE__ */ jsx("div", { className: s.actions(), children: r.actions }) : null
111
+ ] }, id);
112
+ });
113
+ }
114
+ const ul = /* @__PURE__ */ jsxs("ul", { "aria-label": label, "aria-busy": loading || void 0, className: s.ul(), children: [
115
+ before > 0 ? /* @__PURE__ */ jsx("li", { "aria-hidden": true, style: { height: before } }) : null,
116
+ body,
117
+ after > 0 ? /* @__PURE__ */ jsx("li", { "aria-hidden": true, style: { height: after } }) : null
118
+ ] });
119
+ return /* @__PURE__ */ jsxs("div", { className: s.root({ className }), children: [
120
+ loading ? /* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", children: labels.loading }) : null,
121
+ virtualize ? /* @__PURE__ */ jsx("div", { tabIndex: 0, role: "region", "aria-label": label, className: s.scroller(), style: { height: virtualize.height }, onScroll: (e) => setScrollTop(e.currentTarget.scrollTop), children: ul }) : ul,
122
+ footer ? /* @__PURE__ */ jsx("div", { className: s.footer(), children: footer }) : null
123
+ ] });
124
+ }
125
+ export {
126
+ List,
127
+ list,
128
+ listLabels
129
+ };
130
+ //# sourceMappingURL=list.js.map