@krizaka/ui 3.54.0 → 3.55.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 (495) hide show
  1. package/README.md +1 -0
  2. package/dist/account-menu.d.ts +6 -2
  3. package/dist/account-menu.js +8 -1
  4. package/dist/account-menu.js.map +1 -1
  5. package/dist/account-settings.js +28 -88
  6. package/dist/account-settings.js.map +1 -1
  7. package/dist/anatomy-plate.d.ts +4 -1
  8. package/dist/anatomy-plate.js +4 -0
  9. package/dist/anatomy-plate.js.map +1 -1
  10. package/dist/app-header/search.d.ts +63 -0
  11. package/dist/app-header/search.js +70 -0
  12. package/dist/app-header/search.js.map +1 -0
  13. package/dist/app-header.d.ts +88 -4
  14. package/dist/app-header.js +63 -5
  15. package/dist/app-header.js.map +1 -1
  16. package/dist/app-shell.js +31 -40
  17. package/dist/app-shell.js.map +1 -1
  18. package/dist/argument-card.js +3 -3
  19. package/dist/bird-plate.d.ts +3 -1
  20. package/dist/bird-plate.js +2 -2
  21. package/dist/bird-plate.js.map +1 -1
  22. package/dist/blocks.css +162 -27
  23. package/dist/chat.js +2 -2
  24. package/dist/chat.js.map +1 -1
  25. package/dist/checkbox.js +1 -1
  26. package/dist/checkbox.js.map +1 -1
  27. package/dist/chip.js +5 -98
  28. package/dist/chip.js.map +1 -1
  29. package/dist/choice-grid.js +28 -88
  30. package/dist/choice-grid.js.map +1 -1
  31. package/dist/{chunk-YGIN2YIY.js → chunk-3X3OF4TI.js} +2 -2
  32. package/dist/chunk-3X3OF4TI.js.map +1 -0
  33. package/dist/chunk-5VEVYDVC.js +11 -0
  34. package/dist/chunk-5VEVYDVC.js.map +1 -0
  35. package/dist/chunk-7U5TXA5Q.js +105 -0
  36. package/dist/chunk-7U5TXA5Q.js.map +1 -0
  37. package/dist/{chunk-KBQD6HE3.js → chunk-AEP3K4YD.js} +3 -3
  38. package/dist/{chunk-KBQD6HE3.js.map → chunk-AEP3K4YD.js.map} +1 -1
  39. package/dist/chunk-BDIU5LZB.js +18 -0
  40. package/dist/chunk-BDIU5LZB.js.map +1 -0
  41. package/dist/chunk-CSRKYZ53.js +39 -0
  42. package/dist/chunk-CSRKYZ53.js.map +1 -0
  43. package/dist/chunk-HEKDKM5Y.js +128 -0
  44. package/dist/chunk-HEKDKM5Y.js.map +1 -0
  45. package/dist/chunk-KGLRZMCY.js +16 -0
  46. package/dist/chunk-KGLRZMCY.js.map +1 -0
  47. package/dist/chunk-KID32IRJ.js +18 -0
  48. package/dist/chunk-KID32IRJ.js.map +1 -0
  49. package/dist/{chunk-ZQW7LF4Y.js → chunk-OIMXKRXF.js} +2 -2
  50. package/dist/{chunk-YHKTYFOQ.js → chunk-QWKCNSPF.js} +271 -47
  51. package/dist/chunk-QWKCNSPF.js.map +1 -0
  52. package/dist/{chunk-4LYKBSOG.js → chunk-USPOIQV5.js} +2 -2
  53. package/dist/chunk-USPOIQV5.js.map +1 -0
  54. package/dist/{chunk-7NRSPHAF.js → chunk-VB7MWE2N.js} +2 -2
  55. package/dist/{chunk-7NRSPHAF.js.map → chunk-VB7MWE2N.js.map} +1 -1
  56. package/dist/chunk-VIPSZXO4.js +103 -0
  57. package/dist/chunk-VIPSZXO4.js.map +1 -0
  58. package/dist/chunk-YCZ7N6Q6.js +385 -0
  59. package/dist/chunk-YCZ7N6Q6.js.map +1 -0
  60. package/dist/code-block.js +81 -98
  61. package/dist/code-block.js.map +1 -1
  62. package/dist/combobox.js +2 -2
  63. package/dist/component-page.d.ts +4 -1
  64. package/dist/component-page.js +5 -0
  65. package/dist/component-page.js.map +1 -1
  66. package/dist/continue-prompt.d.ts +4 -1
  67. package/dist/continue-prompt.js +4 -0
  68. package/dist/continue-prompt.js.map +1 -1
  69. package/dist/data-table.d.ts +60 -4
  70. package/dist/data-table.js +19 -7
  71. package/dist/date-picker.js +2 -2
  72. package/dist/date-picker.js.map +1 -1
  73. package/dist/detail-layout.d.ts +28 -17
  74. package/dist/detail-layout.js +73 -16
  75. package/dist/detail-layout.js.map +1 -1
  76. package/dist/doodle.d.ts +21 -0
  77. package/dist/doodle.js +39 -0
  78. package/dist/doodle.js.map +1 -0
  79. package/dist/drop-overlay.d.ts +12 -4
  80. package/dist/drop-overlay.js +16 -6
  81. package/dist/drop-overlay.js.map +1 -1
  82. package/dist/elephant.d.ts +2 -0
  83. package/dist/elephant.js +4 -0
  84. package/dist/elephant.js.map +1 -1
  85. package/dist/field.js +1 -1
  86. package/dist/field.js.map +1 -1
  87. package/dist/filter-bar.js +2 -2
  88. package/dist/force-update-screen.d.ts +5 -1
  89. package/dist/force-update-screen.js +4 -0
  90. package/dist/force-update-screen.js.map +1 -1
  91. package/dist/gallery-page.d.ts +4 -1
  92. package/dist/gallery-page.js +4 -0
  93. package/dist/gallery-page.js.map +1 -1
  94. package/dist/genui.js +5 -5
  95. package/dist/image-cropper.d.ts +10 -2
  96. package/dist/image-cropper.js +4 -0
  97. package/dist/image-cropper.js.map +1 -1
  98. package/dist/kanban.d.ts +3 -0
  99. package/dist/kanban.js +4 -0
  100. package/dist/kanban.js.map +1 -1
  101. package/dist/landscape.d.ts +4 -1
  102. package/dist/landscape.js +4 -0
  103. package/dist/landscape.js.map +1 -1
  104. package/dist/list.js +1 -1
  105. package/dist/maintenance-screen.d.ts +5 -1
  106. package/dist/maintenance-screen.js +4 -0
  107. package/dist/maintenance-screen.js.map +1 -1
  108. package/dist/map.js +6 -0
  109. package/dist/map.js.map +1 -1
  110. package/dist/markdown.d.ts +5 -1
  111. package/dist/markdown.js +12 -5
  112. package/dist/markdown.js.map +1 -1
  113. package/dist/match-dialog.d.ts +4 -1
  114. package/dist/match-dialog.js +4 -0
  115. package/dist/match-dialog.js.map +1 -1
  116. package/dist/media-capture.d.ts +6 -1
  117. package/dist/media-capture.js +4 -0
  118. package/dist/media-capture.js.map +1 -1
  119. package/dist/meter.js +5 -121
  120. package/dist/meter.js.map +1 -1
  121. package/dist/native/map.js +6 -0
  122. package/dist/native/map.js.map +1 -1
  123. package/dist/native/markdown.d.ts +9 -2
  124. package/dist/native/markdown.js +46 -7
  125. package/dist/native/markdown.js.map +1 -1
  126. package/dist/native/media-capture.d.ts +1 -0
  127. package/dist/native/media-capture.js +5 -0
  128. package/dist/native/media-capture.js.map +1 -1
  129. package/dist/native/vertical-video.d.ts +8 -2
  130. package/dist/native/vertical-video.js +6 -0
  131. package/dist/native/vertical-video.js.map +1 -1
  132. package/dist/native.d.ts +94 -4
  133. package/dist/native.js +1236 -1110
  134. package/dist/native.js.map +1 -1
  135. package/dist/nav-bar/me.d.ts +32 -0
  136. package/dist/nav-bar/me.js +23 -0
  137. package/dist/nav-bar/me.js.map +1 -0
  138. package/dist/nav-bar.d.ts +60 -2
  139. package/dist/nav-bar.js +92 -48
  140. package/dist/nav-bar.js.map +1 -1
  141. package/dist/notification-preferences.d.ts +151 -0
  142. package/dist/notification-preferences.js +77 -0
  143. package/dist/notification-preferences.js.map +1 -0
  144. package/dist/page-header.js +1 -1
  145. package/dist/page-header.js.map +1 -1
  146. package/dist/pointer-light.js +5 -0
  147. package/dist/pointer-light.js.map +1 -1
  148. package/dist/product-page.d.ts +4 -1
  149. package/dist/product-page.js +4 -0
  150. package/dist/product-page.js.map +1 -1
  151. package/dist/profile-card.d.ts +119 -1
  152. package/dist/profile-card.js +68 -21
  153. package/dist/profile-card.js.map +1 -1
  154. package/dist/promise-card.d.ts +4 -1
  155. package/dist/promise-card.js +4 -0
  156. package/dist/promise-card.js.map +1 -1
  157. package/dist/quota-meter.d.ts +113 -0
  158. package/dist/quota-meter.js +58 -0
  159. package/dist/quota-meter.js.map +1 -0
  160. package/dist/radio-group.js +6 -8
  161. package/dist/radio-group.js.map +1 -1
  162. package/dist/rail-nav.d.ts +18 -2
  163. package/dist/rail-nav.js +25 -2
  164. package/dist/rail-nav.js.map +1 -1
  165. package/dist/retro-tv.d.ts +30 -0
  166. package/dist/retro-tv.js +124 -0
  167. package/dist/retro-tv.js.map +1 -0
  168. package/dist/router.d.ts +12 -1
  169. package/dist/router.js +85 -8
  170. package/dist/router.js.map +1 -1
  171. package/dist/scroll-stage.d.ts +5 -1
  172. package/dist/scroll-stage.js +5 -0
  173. package/dist/scroll-stage.js.map +1 -1
  174. package/dist/search-field.js +1 -1
  175. package/dist/showcase.d.ts +9 -2
  176. package/dist/showcase.js +5 -0
  177. package/dist/showcase.js.map +1 -1
  178. package/dist/signature.d.ts +19 -0
  179. package/dist/signature.js +39 -0
  180. package/dist/signature.js.map +1 -0
  181. package/dist/site-footer.js +1 -1
  182. package/dist/sites.js +1 -1
  183. package/dist/sites.js.map +1 -1
  184. package/dist/slot.d.ts +1 -1
  185. package/dist/stat.js +1 -1
  186. package/dist/stat.js.map +1 -1
  187. package/dist/status-page.d.ts +4 -1
  188. package/dist/status-page.js +5 -0
  189. package/dist/status-page.js.map +1 -1
  190. package/dist/stuck.d.ts +27 -0
  191. package/dist/stuck.js +26 -0
  192. package/dist/stuck.js.map +1 -0
  193. package/dist/swipe-deck.d.ts +9 -2
  194. package/dist/swipe-deck.js +5 -0
  195. package/dist/swipe-deck.js.map +1 -1
  196. package/dist/switch.js +4 -32
  197. package/dist/switch.js.map +1 -1
  198. package/dist/tabs.d.ts +47 -8
  199. package/dist/tabs.js +62 -12
  200. package/dist/tabs.js.map +1 -1
  201. package/dist/tag-input.js +2 -2
  202. package/dist/tag-selector.js +1 -1
  203. package/dist/terminal-replay.d.ts +4 -1
  204. package/dist/terminal-replay.js +4 -0
  205. package/dist/terminal-replay.js.map +1 -1
  206. package/dist/tree-view.js +4 -0
  207. package/dist/tree-view.js.map +1 -1
  208. package/dist/update-prompt.d.ts +5 -1
  209. package/dist/update-prompt.js +4 -0
  210. package/dist/update-prompt.js.map +1 -1
  211. package/dist/video-player.js +7 -376
  212. package/dist/video-player.js.map +1 -1
  213. package/dist/video-trimmer.d.ts +6 -1
  214. package/dist/video-trimmer.js +4 -0
  215. package/dist/video-trimmer.js.map +1 -1
  216. package/package.json +141 -29
  217. package/registry/account-menu.json +9 -8
  218. package/registry/account-settings.json +2 -2
  219. package/registry/achievement.json +3 -4
  220. package/registry/action-bar.json +3 -3
  221. package/registry/action-sheet.json +1 -0
  222. package/registry/activity-feed.json +2 -1
  223. package/registry/agenda.json +1 -1
  224. package/registry/alert.json +1 -1
  225. package/registry/anatomy-plate.json +13 -5
  226. package/registry/app-header.json +470 -23
  227. package/registry/app-shell.json +2 -2
  228. package/registry/argument-card.json +1 -1
  229. package/registry/audio-player.json +1 -1
  230. package/registry/auth-layout.json +1 -1
  231. package/registry/avatar.json +3 -2
  232. package/registry/badge.json +2 -1
  233. package/registry/bird-plate.json +16 -2
  234. package/registry/button.json +7 -6
  235. package/registry/captcha.json +1 -1
  236. package/registry/card-grid.json +1 -1
  237. package/registry/card.json +7 -6
  238. package/registry/catalogue-page.json +3 -4
  239. package/registry/changelog-page.json +3 -5
  240. package/registry/chapter.json +1 -1
  241. package/registry/chat.json +3 -2
  242. package/registry/checkbox.json +4 -3
  243. package/registry/chip-link.json +2 -2
  244. package/registry/chip-row.json +2 -2
  245. package/registry/chip.json +3 -2
  246. package/registry/choice-grid.json +3 -4
  247. package/registry/code-block.json +1 -1
  248. package/registry/combobox.json +3 -2
  249. package/registry/command.json +2 -2
  250. package/registry/comparison-table.json +1 -1
  251. package/registry/component-page.json +14 -5
  252. package/registry/confirm-button.json +4 -4
  253. package/registry/contact-page.json +1 -1
  254. package/registry/continue-prompt.json +13 -5
  255. package/registry/countdown.json +4 -3
  256. package/registry/cover-hero.json +3 -4
  257. package/registry/cta-panel.json +1 -1
  258. package/registry/dashboard-layout.json +1 -1
  259. package/registry/data-table.json +63 -7
  260. package/registry/date-picker.json +5 -4
  261. package/registry/decision-list.json +1 -1
  262. package/registry/description-list.json +2 -1
  263. package/registry/detail-layout.json +30 -6
  264. package/registry/dialog.json +7 -6
  265. package/registry/docs-article-page.json +3 -4
  266. package/registry/docs-hub-page.json +1 -1
  267. package/registry/docs-layout.json +1 -1
  268. package/registry/docs-nav.json +1 -1
  269. package/registry/document-viewer.json +3 -5
  270. package/registry/doodle.json +209 -0
  271. package/registry/drop-overlay.json +30 -16
  272. package/registry/dropdown-menu.json +2 -2
  273. package/registry/elephant.json +15 -7
  274. package/registry/empty-state.json +2 -1
  275. package/registry/engine-flow.json +1 -1
  276. package/registry/error-page.json +3 -5
  277. package/registry/examples/app-header/family.d.ts +4 -0
  278. package/registry/examples/app-header/family.js +41 -0
  279. package/registry/examples/app-header/family.tsx +37 -0
  280. package/registry/examples/app-header/native/family.d.ts +4 -0
  281. package/registry/examples/app-header/native/family.dark.png +0 -0
  282. package/registry/examples/app-header/native/family.js +25 -0
  283. package/registry/examples/app-header/native/family.light.png +0 -0
  284. package/registry/examples/app-header/native/family.tsx +33 -0
  285. package/registry/examples/data-table/applicant-files.d.ts +4 -0
  286. package/registry/examples/data-table/applicant-files.js +24 -0
  287. package/registry/examples/data-table/applicant-files.tsx +23 -0
  288. package/registry/examples/data-table/checks.d.ts +4 -0
  289. package/registry/examples/data-table/checks.js +25 -0
  290. package/registry/examples/data-table/checks.tsx +24 -0
  291. package/registry/examples/detail-layout/profile.d.ts +4 -0
  292. package/registry/examples/detail-layout/profile.js +26 -0
  293. package/registry/examples/detail-layout/profile.tsx +21 -0
  294. package/registry/examples/doodle/kinds.d.ts +4 -0
  295. package/registry/examples/doodle/kinds.js +17 -0
  296. package/registry/examples/doodle/kinds.tsx +14 -0
  297. package/registry/examples/doodle/margin.d.ts +4 -0
  298. package/registry/examples/doodle/margin.js +17 -0
  299. package/registry/examples/doodle/margin.tsx +17 -0
  300. package/registry/examples/markdown/native/basic.dark.png +0 -0
  301. package/registry/examples/markdown/native/basic.light.png +0 -0
  302. package/registry/examples/markdown/native/wide-table.d.ts +4 -0
  303. package/registry/examples/markdown/native/wide-table.dark.png +0 -0
  304. package/registry/examples/markdown/native/wide-table.js +23 -0
  305. package/registry/examples/markdown/native/wide-table.light.png +0 -0
  306. package/registry/examples/markdown/native/wide-table.tsx +22 -0
  307. package/registry/examples/markdown/wide-table.d.ts +4 -0
  308. package/registry/examples/markdown/wide-table.js +28 -0
  309. package/registry/examples/markdown/wide-table.tsx +23 -0
  310. package/registry/examples/nav-bar/family-product.js +2 -4
  311. package/registry/examples/nav-bar/family-product.tsx +3 -5
  312. package/registry/examples/notification-preferences/default.d.ts +4 -0
  313. package/registry/examples/notification-preferences/default.js +29 -0
  314. package/registry/examples/notification-preferences/default.tsx +28 -0
  315. package/registry/examples/profile-card/banner.d.ts +4 -0
  316. package/registry/examples/profile-card/banner.js +28 -0
  317. package/registry/examples/profile-card/banner.tsx +24 -0
  318. package/registry/examples/profile-card/native/banner.d.ts +4 -0
  319. package/registry/examples/profile-card/native/banner.dark.png +0 -0
  320. package/registry/examples/profile-card/native/banner.js +22 -0
  321. package/registry/examples/profile-card/native/banner.light.png +0 -0
  322. package/registry/examples/profile-card/native/banner.tsx +18 -0
  323. package/registry/examples/quota-meter/default.d.ts +4 -0
  324. package/registry/examples/quota-meter/default.js +26 -0
  325. package/registry/examples/quota-meter/default.tsx +20 -0
  326. package/registry/examples/quota-meter/full.d.ts +4 -0
  327. package/registry/examples/quota-meter/full.js +25 -0
  328. package/registry/examples/quota-meter/full.tsx +18 -0
  329. package/registry/examples/rail-nav/shortcuts.d.ts +4 -0
  330. package/registry/examples/rail-nav/shortcuts.js +49 -0
  331. package/registry/examples/rail-nav/shortcuts.tsx +40 -0
  332. package/registry/examples/retro-tv/cabinet.d.ts +4 -0
  333. package/registry/examples/retro-tv/cabinet.js +12 -0
  334. package/registry/examples/retro-tv/cabinet.tsx +7 -0
  335. package/registry/examples/retro-tv/portable.d.ts +4 -0
  336. package/registry/examples/retro-tv/portable.js +12 -0
  337. package/registry/examples/retro-tv/portable.tsx +7 -0
  338. package/registry/examples/signature/both.d.ts +4 -0
  339. package/registry/examples/signature/both.js +11 -0
  340. package/registry/examples/signature/both.tsx +6 -0
  341. package/registry/examples/signature/variants.d.ts +4 -0
  342. package/registry/examples/signature/variants.js +14 -0
  343. package/registry/examples/signature/variants.tsx +11 -0
  344. package/registry/examples/stuck/card.d.ts +4 -0
  345. package/registry/examples/stuck/card.js +13 -0
  346. package/registry/examples/stuck/card.tsx +14 -0
  347. package/registry/examples/stuck/holds.d.ts +4 -0
  348. package/registry/examples/stuck/holds.js +12 -0
  349. package/registry/examples/stuck/holds.tsx +16 -0
  350. package/registry/examples/stuck/tag.d.ts +4 -0
  351. package/registry/examples/stuck/tag.js +12 -0
  352. package/registry/examples/stuck/tag.tsx +13 -0
  353. package/registry/examples/tabs/binder.d.ts +4 -0
  354. package/registry/examples/tabs/binder.js +22 -0
  355. package/registry/examples/tabs/binder.tsx +20 -0
  356. package/registry/examples/tabs/native/binder.d.ts +4 -0
  357. package/registry/examples/tabs/native/binder.dark.png +0 -0
  358. package/registry/examples/tabs/native/binder.js +26 -0
  359. package/registry/examples/tabs/native/binder.light.png +0 -0
  360. package/registry/examples/tabs/native/binder.tsx +22 -0
  361. package/registry/fab.json +1 -0
  362. package/registry/field.json +3 -2
  363. package/registry/file-upload.json +6 -11
  364. package/registry/filter-bar.json +2 -2
  365. package/registry/flock.json +3 -4
  366. package/registry/footnote.json +2 -3
  367. package/registry/force-update-screen.json +14 -5
  368. package/registry/form.json +5 -4
  369. package/registry/gallery-page.json +14 -5
  370. package/registry/genui.json +2 -2
  371. package/registry/glossary-term.json +1 -1
  372. package/registry/glossary.json +1 -1
  373. package/registry/glow-card.json +2 -2
  374. package/registry/goal-gauge.json +2 -1
  375. package/registry/header.json +1 -0
  376. package/registry/how-it-works-page.json +3 -5
  377. package/registry/image-cropper.json +13 -5
  378. package/registry/image-viewer.json +3 -4
  379. package/registry/index.json +301 -87
  380. package/registry/iso.json +1 -1
  381. package/registry/kanban.json +13 -5
  382. package/registry/kbd.json +1 -1
  383. package/registry/kpi-explained.json +2 -2
  384. package/registry/landing-page.json +3 -5
  385. package/registry/landscape.json +13 -5
  386. package/registry/language-switch.json +1 -1
  387. package/registry/legal-page.json +1 -1
  388. package/registry/link-card.json +1 -1
  389. package/registry/list.json +2 -1
  390. package/registry/loader.json +2 -1
  391. package/registry/longform-page.json +1 -1
  392. package/registry/maintenance-screen.json +14 -5
  393. package/registry/map.json +3 -2
  394. package/registry/markdown.json +86 -9
  395. package/registry/marketing-layout.json +1 -1
  396. package/registry/marquee.json +1 -1
  397. package/registry/mascot-quote.json +1 -1
  398. package/registry/mascot-state.json +12 -11
  399. package/registry/mascots.json +2 -1
  400. package/registry/match-dialog.json +14 -5
  401. package/registry/media-capture.json +14 -5
  402. package/registry/media-gallery.json +3 -5
  403. package/registry/media-grid.json +1 -1
  404. package/registry/media-picker.json +2 -3
  405. package/registry/meta-row.json +2 -1
  406. package/registry/meter.json +4 -3
  407. package/registry/nav-bar.json +100 -9
  408. package/registry/next-actions.json +1 -1
  409. package/registry/notification-preferences.json +250 -0
  410. package/registry/number-ticker.json +2 -1
  411. package/registry/onboarding.json +1 -0
  412. package/registry/opening-hours.json +1 -1
  413. package/registry/otp-input.json +1 -0
  414. package/registry/page-header.json +2 -2
  415. package/registry/page-hero.json +1 -1
  416. package/registry/page-index.json +1 -1
  417. package/registry/page.json +3 -3
  418. package/registry/pagination.json +2 -1
  419. package/registry/permission-prompt.json +2 -2
  420. package/registry/photo-grid.json +4 -4
  421. package/registry/pointer-light.json +6 -2
  422. package/registry/popover.json +2 -2
  423. package/registry/pricing-page.json +4 -6
  424. package/registry/product-page.json +14 -5
  425. package/registry/profile-card.json +232 -8
  426. package/registry/progress.json +4 -3
  427. package/registry/promise-card.json +13 -5
  428. package/registry/pull-to-refresh.json +1 -0
  429. package/registry/quota-meter.json +308 -0
  430. package/registry/radio-group.json +4 -3
  431. package/registry/rail-nav.json +48 -10
  432. package/registry/recipes.json +1 -1
  433. package/registry/retro-tv.json +478 -0
  434. package/registry/router.json +3 -3
  435. package/registry/screen.json +1 -0
  436. package/registry/scroll-stage.json +14 -5
  437. package/registry/search-field.json +3 -2
  438. package/registry/section-backdrop.json +1 -1
  439. package/registry/segmented.json +1 -0
  440. package/registry/separator.json +2 -2
  441. package/registry/service-card.json +1 -1
  442. package/registry/settings-layout.json +2 -1
  443. package/registry/showcase.json +14 -5
  444. package/registry/signature.json +185 -0
  445. package/registry/site-footer.json +3 -3
  446. package/registry/sites.json +2 -2
  447. package/registry/skeleton.json +2 -1
  448. package/registry/skip-link.json +1 -1
  449. package/registry/slider.json +5 -4
  450. package/registry/slot-picker.json +1 -1
  451. package/registry/slot.json +2 -2
  452. package/registry/specimen-tag.json +1 -1
  453. package/registry/spinner.json +4 -3
  454. package/registry/splash-handoff.json +1 -0
  455. package/registry/split-view.json +1 -1
  456. package/registry/stage-banner.json +2 -3
  457. package/registry/stat.json +2 -2
  458. package/registry/status-page.json +13 -5
  459. package/registry/step-progress.json +2 -1
  460. package/registry/step-showcase.json +3 -5
  461. package/registry/stepper.json +2 -1
  462. package/registry/sticky-action.json +1 -1
  463. package/registry/stuck.json +219 -0
  464. package/registry/swipe-deck.json +14 -5
  465. package/registry/swipeable-row.json +1 -0
  466. package/registry/switch.json +3 -2
  467. package/registry/tab-bar.json +1 -0
  468. package/registry/tabs.json +154 -22
  469. package/registry/tag-input.json +1 -1
  470. package/registry/tag-selector.json +2 -1
  471. package/registry/taped-photo.json +1 -1
  472. package/registry/terminal-replay.json +14 -5
  473. package/registry/text-style.json +5 -5
  474. package/registry/theme.json +2 -1
  475. package/registry/toast.json +2 -1
  476. package/registry/toc.json +1 -1
  477. package/registry/tooltip.json +2 -2
  478. package/registry/tree-view.json +6 -2
  479. package/registry/txt.json +1 -0
  480. package/registry/update-prompt.json +14 -5
  481. package/registry/upload-queue.json +1 -1
  482. package/registry/verified-badge.json +6 -6
  483. package/registry/vertical-video.json +8 -3
  484. package/registry/video-player.json +5 -6
  485. package/registry/video-trimmer.json +13 -5
  486. package/registry/virtual.json +2 -2
  487. package/registry/waveform.json +4 -3
  488. package/dist/chunk-4LYKBSOG.js.map +0 -1
  489. package/dist/chunk-HHFWK2HH.js +0 -163
  490. package/dist/chunk-HHFWK2HH.js.map +0 -1
  491. package/dist/chunk-R3LTSMS5.js +0 -75
  492. package/dist/chunk-R3LTSMS5.js.map +0 -1
  493. package/dist/chunk-YGIN2YIY.js.map +0 -1
  494. package/dist/chunk-YHKTYFOQ.js.map +0 -1
  495. /package/dist/{chunk-ZQW7LF4Y.js.map → chunk-OIMXKRXF.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/data-table/csv.ts","../src/data-table/data-table.tsx","../src/pagination/pagination.tsx","../src/data-table/engine.ts","../src/data-table/use-route-table.ts","../src/data-table/route-codec.ts","../src/data-table/toolbar.tsx","../src/field/field.tsx"],"sourcesContent":["// CSV (RFC 4180) from rows and columns: the header of each column, then each row's values — what `value` returns (or\n// `row[id]`), never the rendered cell. Dates as ISO 8601; a value that a spreadsheet would run as a formula is quoted\n// with a leading apostrophe (CSV injection).\nimport type { CellValue } from \"./engine\";\n\ntype CsvColumn<T> = { id: string; header: string; value?: (row: T) => CellValue };\n\nconst FORMULA = /^[=+\\-@\\t\\r]/;\n\nfunction field(value: CellValue): string {\n let text = value == null ? \"\" : value instanceof Date ? value.toISOString() : String(value);\n if (typeof value === \"string\" && FORMULA.test(text)) text = `'${text}`;\n return /[\",\\n\\r;]/.test(text) || text !== text.trim() ? `\"${text.replace(/\"/g, '\"\"')}\"` : text;\n}\n\n/** The rows as CSV text: a header line, then one line per row, separated by `\\r\\n`. */\nexport function dataTableCsv<T>(rows: readonly T[], columns: readonly CsvColumn<T>[], separator = \",\"): string {\n const lines = [columns.map((column) => field(column.header)).join(separator)];\n for (const row of rows) {\n lines.push(columns.map((column) => field(column.value ? column.value(row) : ((row as Record<string, unknown>)[column.id] as CellValue))).join(separator));\n }\n return lines.join(\"\\r\\n\");\n}\n","// Client (the table's state, the windowing of long lists). A real `<table>` with a caption and column headers\n// (`scope=\"col\"`, `aria-sort` on the sorted one) that turns into a stack of cards in a narrow container — one DOM, the\n// roles written out so that the change of `display` never loses the table's semantics. The engine is TanStack Table v9\n// (engine.ts): sorting, filters and facets, grouping, expanding, pagination, selection, visibility, pinning, resizing —\n// in the browser, or on the server (`manual` + `onStateChange`). Long lists render by what is in view (`virtualized`).\nimport { useTable } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Checkbox } from \"../checkbox\";\nimport { cn } from \"../cn\";\nimport { ChevronGlyph, SortGlyph } from \"../glyphs\";\nimport { useControllable } from \"../media\";\nimport { Pagination, type PaginationLabels } from \"../pagination\";\nimport { useLayoutFallbacks, useVirtualizer } from \"../virtual/virtual\";\nimport {\n type CellValue,\n type ColumnDef,\n type ColumnResizingState,\n type DataTableFilterState,\n type DataTableInstance,\n features,\n FILTERS,\n type FilterValue,\n type RowData,\n sortByValue,\n type TableCell,\n type TableColumn,\n type TableRow,\n} from \"./engine\";\nimport { useRouteTable } from \"./use-route-table\";\n\nexport const dataTable = tv({\n slots: {\n root: \"@container w-full overflow-clip rounded-xl border border-border-default bg-surface-1\",\n toolbar: \"border-b border-border-default p-3\",\n scroller: \"w-full overflow-x-auto\",\n table: \"w-full border-collapse text-left text-sm text-fg\",\n caption: \"px-4 pt-4 pb-2 text-left text-sm font-semibold text-fg\",\n thead: \"bg-surface-2/60\",\n headRow: \"border-b border-border-default\",\n th: \"relative whitespace-nowrap px-4 py-3 text-xs font-semibold text-fg-secondary\",\n sortButton:\n \"-mx-1.5 inline-flex items-center gap-1 rounded-md px-1.5 py-1 hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[pressed=true]:text-fg\",\n resizer:\n \"absolute top-0 right-0 h-full w-1.5 cursor-col-resize touch-none select-none bg-transparent hover:bg-border-strong \" +\n \"focus-visible:bg-accent focus-visible:outline-hidden data-[resizing]:bg-accent\",\n tbody: \"\",\n tr: \"border-b border-border-subtle transition-colors last:border-b-0 hover:bg-surface-2/50 data-[state=selected]:bg-accent-soft\",\n groupRow: \"bg-surface-2/40 font-semibold\",\n td: \"px-4 py-3 align-middle\",\n select: \"w-10\",\n expander: \"w-10\",\n toggle:\n \"inline-flex h-7 min-w-7 items-center justify-center gap-1.5 rounded-md text-fg-secondary hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring [&[aria-expanded=true]>svg]:rotate-90 [&>svg]:transition-transform motion-reduce:[&>svg]:transition-none\",\n detail: \"bg-surface-0 px-4 py-4\",\n message: \"px-4 py-10 text-center text-sm text-fg-secondary\",\n skeleton: \"h-4 w-full max-w-40 animate-pulse rounded bg-surface-3 motion-reduce:animate-none\",\n footer: \"border-t border-border-default px-4 py-3\",\n },\n variants: {\n layout: {\n table: {\n th: \"data-[pin]:sticky data-[pin]:z-[2] data-[pin]:bg-surface-2 data-[pin=start]:left-(--dt-pin) data-[pin=end]:right-(--dt-pin)\",\n td: \"data-[pin]:sticky data-[pin]:z-[1] data-[pin]:bg-surface-1 data-[pin=start]:left-(--dt-pin) data-[pin=end]:right-(--dt-pin)\",\n },\n // Below 36rem of container: cards. The sortable headers stay, as a row of sort buttons above the cards.\n auto: {\n table: \"@max-xl:block\",\n caption: \"@max-xl:block\",\n thead: \"@max-xl:sr-only @max-xl:bg-transparent @max-xl:has-[[data-keep]]:not-sr-only @max-xl:has-[[data-keep]]:block\",\n headRow: \"@max-xl:flex @max-xl:flex-wrap @max-xl:items-center @max-xl:gap-2 @max-xl:px-3 @max-xl:py-2\",\n th:\n \"@max-xl:sr-only @max-xl:data-[keep]:not-sr-only @max-xl:data-[keep]:block @max-xl:p-0 \" +\n \"@xl:data-[pin]:sticky @xl:data-[pin]:z-[2] @xl:data-[pin]:bg-surface-2 @xl:data-[pin=start]:left-(--dt-pin) @xl:data-[pin=end]:right-(--dt-pin)\",\n tbody: \"@max-xl:grid @max-xl:gap-3 @max-xl:p-3\",\n tr: \"@max-xl:relative @max-xl:grid @max-xl:gap-1.5 @max-xl:rounded-xl @max-xl:border @max-xl:border-border-default @max-xl:bg-surface-0 @max-xl:p-4 @max-xl:last:border-b\",\n td:\n \"@max-xl:flex @max-xl:min-w-0 @max-xl:items-baseline @max-xl:justify-between @max-xl:gap-4 @max-xl:p-0 @max-xl:text-right @max-xl:[overflow-wrap:anywhere] \" +\n \"@max-xl:[&>*]:min-w-0 @max-xl:[&>*]:shrink @max-xl:[&>*]:whitespace-normal \" +\n \"@max-xl:before:shrink-0 @max-xl:before:text-xs @max-xl:before:font-semibold @max-xl:before:text-fg-secondary @max-xl:before:content-[attr(data-label)] \" +\n \"@max-xl:data-[card=title]:order-first @max-xl:data-[card=title]:pr-8 @max-xl:data-[card=title]:text-left @max-xl:data-[card=title]:text-base @max-xl:data-[card=title]:font-semibold @max-xl:data-[card=title]:before:content-none \" +\n \"@max-xl:data-[card=hidden]:hidden @max-xl:data-[card=message]:block @max-xl:data-[card=message]:text-center @max-xl:data-[card=message]:before:content-none \" +\n \"@xl:data-[pin]:sticky @xl:data-[pin]:z-[1] @xl:data-[pin]:bg-surface-1 @xl:data-[pin=start]:left-(--dt-pin) @xl:data-[pin=end]:right-(--dt-pin)\",\n select: \"@max-xl:absolute @max-xl:right-3 @max-xl:top-3 @max-xl:w-auto @max-xl:before:content-none\",\n expander: \"@max-xl:before:content-none\",\n },\n cards: {\n table: \"block\",\n caption: \"block\",\n thead: \"sr-only bg-transparent has-[[data-keep]]:not-sr-only has-[[data-keep]]:block\",\n headRow: \"flex flex-wrap items-center gap-2 px-3 py-2\",\n th: \"sr-only p-0 data-[keep]:not-sr-only data-[keep]:block\",\n tbody: \"grid gap-3 p-3\",\n tr: \"relative grid gap-1.5 rounded-xl border border-border-default bg-surface-0 p-4 last:border-b\",\n td:\n \"flex min-w-0 items-baseline justify-between gap-4 p-0 text-right [overflow-wrap:anywhere] before:shrink-0 before:text-xs before:font-semibold before:text-fg-secondary before:content-[attr(data-label)] \" +\n \"[&>*]:min-w-0 [&>*]:shrink [&>*]:whitespace-normal \" +\n \"data-[card=title]:order-first data-[card=title]:pr-8 data-[card=title]:text-left data-[card=title]:text-base data-[card=title]:font-semibold data-[card=title]:before:content-none \" +\n \"data-[card=hidden]:hidden data-[card=message]:block data-[card=message]:text-center data-[card=message]:before:content-none\",\n select: \"absolute right-3 top-3 w-auto before:content-none\",\n expander: \"before:content-none\",\n },\n },\n density: {\n comfortable: {},\n compact: { th: \"py-2\", td: \"py-1.5\" },\n },\n // The header stays in view while the page scrolls (table layouts only; `--dt-top` clears a fixed bar).\n sticky: { true: {}, false: {} },\n // Zebra rows (the table layouts); the cards keep their frame.\n striped: { true: {}, false: {} },\n // Typed columns: one height per row (`typed`); untyped tables keep the height of their content.\n typed: { true: {}, false: {} },\n // What a row becomes on a phone (under 36 rem, or with `layout=\"cards\"`): a card, or a list row (#636).\n phone: { cards: {}, list: {} },\n },\n compoundVariants: [\n { layout: \"table\", sticky: true, class: { th: \"sticky top-(--dt-top,0px) z-[3] bg-surface-2\" } },\n { layout: \"auto\", sticky: true, class: { th: \"@xl:sticky @xl:top-(--dt-top,0px) @xl:z-[3] @xl:bg-surface-2\" } },\n { layout: \"table\", striped: true, class: { tr: \"even:bg-surface-2/40\" } },\n { layout: \"auto\", striped: true, class: { tr: \"@xl:even:bg-surface-2/40\" } },\n // One row height per density (a two-line row — a name and its id — is the tallest).\n { layout: \"table\", density: \"comfortable\", typed: true, class: { td: \"h-15\" } },\n { layout: \"auto\", density: \"comfortable\", typed: true, class: { td: \"@xl:h-15\" } },\n { layout: \"table\", density: \"compact\", typed: true, class: { td: \"h-12\" } },\n { layout: \"auto\", density: \"compact\", typed: true, class: { td: \"@xl:h-12\" } },\n // The list rows (#636): no box in the box, no label/value lines — the checkbox, the title and its line of facts, the\n // status at the end, a hairline between rows. Each cell says its place in `data-list` (title · status · away).\n {\n layout: \"auto\",\n phone: \"list\",\n class: {\n tbody: \"@max-xl:gap-0 @max-xl:p-0\",\n tr:\n \"@max-xl:flex @max-xl:items-center @max-xl:gap-3 @max-xl:rounded-none @max-xl:border-0 @max-xl:border-b @max-xl:border-border-subtle @max-xl:bg-transparent \" +\n \"@max-xl:px-4 @max-xl:py-3 @max-xl:last:border-b-0\",\n td:\n \"@max-xl:block @max-xl:text-left @max-xl:before:content-none @max-xl:data-[list=title]:min-w-0 @max-xl:data-[list=title]:flex-1 \" +\n \"@max-xl:data-[list=status]:shrink-0 @max-xl:data-[list=away]:hidden @max-xl:data-[card=message]:w-full\",\n select: \"@max-xl:relative @max-xl:right-auto @max-xl:top-auto @max-xl:z-[1] @max-xl:shrink-0 @max-xl:self-center\",\n expander: \"@max-xl:relative @max-xl:z-[1] @max-xl:shrink-0\",\n },\n },\n {\n layout: \"cards\",\n phone: \"list\",\n class: {\n tbody: \"gap-0 p-0\",\n tr: \"flex items-center gap-3 rounded-none border-0 border-b border-border-subtle bg-transparent px-4 py-3 last:border-b-0\",\n td: \"block text-left before:content-none data-[list=title]:min-w-0 data-[list=title]:flex-1 data-[list=status]:shrink-0 data-[list=away]:hidden data-[card=message]:w-full\",\n select: \"relative right-auto top-auto z-[1] shrink-0 self-center\",\n expander: \"relative z-[1] shrink-0\",\n },\n },\n ],\n defaultVariants: { layout: \"auto\", density: \"comfortable\", sticky: false, striped: false, typed: false, phone: \"cards\" },\n});\n\n// Column priorities. `priority: 1` (default) is always in the row; a higher number leaves the row when the table's own\n// width (a container query, not the window's) falls under its tier and goes to the row's detail — the same\n// `@container` that turns the table into cards. Written out in full: Tailwind finds a class only as a whole string.\n// priority 2 → 42rem · 3 → 48rem · 4 → 56rem · 5 → 64rem · 6 → 72rem · 7 → 80rem\n// On the cards (under 36rem), priority 2 stays on the card's face and 3+ go to its detail.\ntype Priority = 2 | 3 | 4 | 5 | 6 | 7;\ntype ByLayout = { auto: Record<Priority, string>; table: Record<Priority, string>; cards: Record<Priority, string> };\nconst NO_CLASS: Record<Priority, string> = { 2: \"\", 3: \"\", 4: \"\", 5: \"\", 6: \"\", 7: \"\" };\n/** The cell of a column that leaves the row. */\nconst LEAVES: ByLayout = {\n auto: { 2: \"@xl:@max-2xl:hidden!\", 3: \"@max-3xl:hidden!\", 4: \"@max-4xl:hidden!\", 5: \"@max-5xl:hidden!\", 6: \"@max-6xl:hidden!\", 7: \"@max-7xl:hidden!\" },\n table: { 2: \"@max-2xl:hidden!\", 3: \"@max-3xl:hidden!\", 4: \"@max-4xl:hidden!\", 5: \"@max-5xl:hidden!\", 6: \"@max-6xl:hidden!\", 7: \"@max-7xl:hidden!\" },\n cards: { 2: \"\", 3: \"hidden!\", 4: \"hidden!\", 5: \"hidden!\", 6: \"hidden!\", 7: \"hidden!\" },\n};\n/** Its header (the cards keep the sort buttons). */\nconst LEAVES_HEAD: ByLayout = {\n auto: { 2: \"@xl:@max-2xl:hidden!\", 3: \"@xl:@max-3xl:hidden!\", 4: \"@xl:@max-4xl:hidden!\", 5: \"@xl:@max-5xl:hidden!\", 6: \"@xl:@max-6xl:hidden!\", 7: \"@xl:@max-7xl:hidden!\" },\n table: LEAVES.table,\n cards: NO_CLASS,\n};\n/** Its line in the row's detail: shown exactly when the cell is not. */\nconst IN_DETAIL: ByLayout = {\n auto: { 2: \"hidden @xl:@max-2xl:grid\", 3: \"hidden @max-3xl:grid\", 4: \"hidden @max-4xl:grid\", 5: \"hidden @max-5xl:grid\", 6: \"hidden @max-6xl:grid\", 7: \"hidden @max-7xl:grid\" },\n table: { 2: \"hidden @max-2xl:grid\", 3: \"hidden @max-3xl:grid\", 4: \"hidden @max-4xl:grid\", 5: \"hidden @max-5xl:grid\", 6: \"hidden @max-6xl:grid\", 7: \"hidden @max-7xl:grid\" },\n cards: { 2: \"hidden\", 3: \"grid\", 4: \"grid\", 5: \"grid\", 6: \"grid\", 7: \"grid\" },\n};\n/** The button that opens the detail, and its panel, keyed by the highest priority of the table: seen only when something left the row. */\nconst TOGGLE: ByLayout = {\n auto: { 2: \"hidden @xl:@max-2xl:inline-flex\", 3: \"hidden @max-3xl:inline-flex\", 4: \"hidden @max-4xl:inline-flex\", 5: \"hidden @max-5xl:inline-flex\", 6: \"hidden @max-6xl:inline-flex\", 7: \"hidden @max-7xl:inline-flex\" },\n table: { 2: \"hidden @max-2xl:inline-flex\", 3: \"hidden @max-3xl:inline-flex\", 4: \"hidden @max-4xl:inline-flex\", 5: \"hidden @max-5xl:inline-flex\", 6: \"hidden @max-6xl:inline-flex\", 7: \"hidden @max-7xl:inline-flex\" },\n cards: { 2: \"hidden\", 3: \"inline-flex\", 4: \"inline-flex\", 5: \"inline-flex\", 6: \"inline-flex\", 7: \"inline-flex\" },\n};\nconst PANEL: ByLayout = {\n auto: { 2: \"hidden @xl:@max-2xl:block\", 3: \"hidden @max-3xl:block\", 4: \"hidden @max-4xl:block\", 5: \"hidden @max-5xl:block\", 6: \"hidden @max-6xl:block\", 7: \"hidden @max-7xl:block\" },\n table: { 2: \"hidden @max-2xl:block\", 3: \"hidden @max-3xl:block\", 4: \"hidden @max-4xl:block\", 5: \"hidden @max-5xl:block\", 6: \"hidden @max-6xl:block\", 7: \"hidden @max-7xl:block\" },\n cards: { 2: \"hidden\", 3: \"block\", 4: \"block\", 5: \"block\", 6: \"block\", 7: \"block\" },\n};\n\n// The list rows (`phone=\"list\"`): the facts line under the title, the columns that go to the row's detail (every\n// priority-1 column that is neither the title nor a status), the button and the panel that show them, the title's link\n// stretched over the row.\nconst LIST_FACTS = { auto: \"hidden @max-xl:mt-0.5 @max-xl:block @max-xl:truncate text-xs font-normal text-fg-secondary\", table: \"hidden\", cards: \"mt-0.5 block truncate text-xs font-normal text-fg-secondary\" } as const;\nconst LIST_IN_DETAIL = { auto: \"hidden @max-xl:grid\", table: \"hidden\", cards: \"grid\" } as const;\nconst LIST_TOGGLE = { auto: \"@max-xl:inline-flex\", table: \"\", cards: \"inline-flex\" } as const;\nconst LIST_PANEL = { auto: \"@max-xl:block\", table: \"\", cards: \"block\" } as const;\nconst LIST_LINK = { auto: \"@max-xl:after:absolute @max-xl:after:inset-0 @max-xl:after:content-['']\", table: \"\", cards: \"after:absolute after:inset-0 after:content-['']\" } as const;\n\nexport type DataTableColumnType = \"title\" | \"badge\" | \"number\" | \"link\" | \"date\" | \"status\" | \"text\";\n\n// What each type does to its cell. Sizes apply to the table layouts only (a card is not a column).\n// title: the column that takes the slack, truncated, full value on hover · badge, status, number, date: as wide as\n// their content, never stretched · link: truncated · text: wraps, two lines.\nconst TYPE_CELL: Record<DataTableColumnType, ByLayoutString> = {\n title: { auto: \"@xl:w-full @xl:max-w-0 @xl:min-w-44\", table: \"w-full max-w-0 min-w-44\", cards: \"\" },\n badge: { auto: \"@xl:w-px\", table: \"w-px\", cards: \"\" },\n status: { auto: \"@xl:w-px @xl:whitespace-nowrap\", table: \"w-px whitespace-nowrap\", cards: \"\" },\n number: { auto: \"@xl:w-px @xl:whitespace-nowrap tabular-nums\", table: \"w-px whitespace-nowrap tabular-nums\", cards: \"tabular-nums\" },\n date: { auto: \"@xl:w-px @xl:whitespace-nowrap tabular-nums\", table: \"w-px whitespace-nowrap tabular-nums\", cards: \"tabular-nums\" },\n link: { auto: \"@xl:min-w-28 @xl:max-w-56\", table: \"min-w-28 max-w-56\", cards: \"\" },\n text: { auto: \"@xl:min-w-36\", table: \"min-w-36\", cards: \"\" },\n};\ntype ByLayoutString = { auto: string; table: string; cards: string };\nconst CLAMP = { 1: \"line-clamp-1\", 2: \"line-clamp-2\", 3: \"line-clamp-3\" } as const;\n\nexport type SortDirection = \"ascending\" | \"descending\";\nexport type DataTableSort = { column: string; direction: SortDirection } | null;\n\n/** What the server needs to fetch a page (`manual` mode): given to `onStateChange` at each change. */\nexport type DataTableQuery = {\n /** The sorted column, or `null`. */\n sort: DataTableSort;\n /** The filters in force, by column id. */\n filters: DataTableFilterState;\n /** The page, from 1 (1 without pagination). */\n page: number;\n /** Rows per page (`Infinity` without pagination). */\n pageSize: number;\n};\n\nexport type DataTableColumn<T> = {\n /** A key of the column (and of the row, for the default value). */\n id: string;\n /** The column's name, passed translated: the header, the label of the value in a card, the filter's name. */\n header: string;\n /** What a cell shows. Default: the value as text. */\n cell?: (row: T) => React.ReactNode;\n /** The value sorted, filtered, grouped and exported. Default `row[id]`. */\n value?: (row: T) => CellValue;\n /** The header becomes a sort button (ascending → descending → none). */\n sortable?: boolean;\n /** How `DataTableFilters` filters it: `text` (a search), `facet` (values to choose), `range` (numbers between bounds). */\n filter?: \"text\" | \"facet\" | \"range\";\n /** The choices of a `facet` filter, with their words (and counts from the server). Default: the values found in the rows. */\n options?: readonly { value: string; label: string; count?: number }[];\n /** The rows can be grouped by this column (`groupBy`). */\n groupable?: boolean;\n /** What a group's row shows in this column, from the group's rows (a sum, a count). */\n aggregate?: (rows: readonly T[]) => React.ReactNode;\n /** Text alignment: `end` for amounts and counts. */\n align?: \"start\" | \"center\" | \"end\";\n /** The width, in px (the starting width when `resizing`). */\n width?: number;\n /** The narrowest the column may be, in px (also what a resized one may shrink to). Default 64. */\n minWidth?: number;\n /** In a card: `title` (the heading of the card), `label` (default: \"Header value\"), `hidden`. */\n card?: \"title\" | \"label\" | \"hidden\";\n /** Hides the header visually (an actions column), keeping it for screen readers. */\n headerHidden?: boolean;\n /** Listed in `DataTableColumnsMenu`, so a person can hide it. Default `true`. */\n hideable?: boolean;\n /**\n * What the column holds, which sizes and aligns it: `title` (the name, takes the slack, truncated, `subtitle` under it in\n * mono — and the card's heading), `badge` · `status` (as wide as the badge, never stretched), `number` (end-aligned,\n * tabular), `date`, `link` (truncated, `href`), `text` (wraps, two lines). Untyped: as before.\n */\n type?: DataTableColumnType;\n /**\n * 1 (default) always in the row; 2 to 7 leave it when the table is narrower than 42 · 48 · 56 · 64 · 72 · 80 rem and\n * go to the row's detail (a chevron opens it); under 36 rem (cards) 2 stays on the card, 3+ go to its detail. In the phone's\n * list rows (`phone=\"list\"`), the 2s are joined as the line of facts under the title.\n */\n priority?: 1 | 2 | 3 | 4 | 5 | 6 | 7;\n /** `title`: the line under the name (an id), in mono. */\n subtitle?: (row: T) => React.ReactNode;\n /** `link`: where the value leads. `title`: the row's page — the name becomes its link (the whole row, in the phone's list rows). */\n href?: (row: T) => string | undefined;\n /** `number`: the unit after the value (muted). */\n unit?: string;\n /** The widest the column may be in the table layouts, in px; longer text is clamped, the full value on hover. */\n maxWidth?: number;\n /** One line only, truncated (the full value on hover). */\n nowrap?: boolean;\n /** Lines of text kept before the ellipsis (default 2 for `text`). */\n clamp?: 1 | 2 | 3;\n};\n\nexport type DataTableLabels = {\n /** The checkbox of the header (\"Select all rows\"). */\n selectAll: string;\n /** The checkbox of a row: `(name) => \"Select \" + name`, the name from `rowLabel`. */\n selectRow: (name: string) => string;\n /** Read while the rows load (\"Loading\"). */\n loading: string;\n /** The default empty state (\"Nothing to show\"). */\n empty: string;\n /** The header of the column of the expand buttons, for screen readers (\"Details\"). */\n details: string;\n /** The button that opens a row: `(name) => \"Show details of \" + name`. */\n expandRow: (name: string) => string;\n /** The button of a group's row: `(value, count) => value + \", \" + count + \" rows\"`. */\n group: (value: string, count: number) => string;\n /** The handle that resizes a column: `(header) => \"Resize \" + header`. */\n resize: (header: string) => string;\n /** The count of results under the filters: `(count) => count + \" rows\"`. */\n results: (count: number) => string;\n /** The accessible name of the filters' bar (\"Filter the table\"). */\n filters: string;\n /** \"Clear filters\". */\n clearFilters: string;\n /** A filter's chip remove button: `(label) => \"Remove \" + label`. */\n removeFilter: (label: string) => string;\n /** The words of a filter in force: `(header, value) => header + \": \" + value`. */\n activeFilter: (header: string, value: string) => string;\n /** A `text` filter's field: `(header) => \"Search \" + header`. */\n search: (header: string) => string;\n /** The lower bound of a `range` filter: `(header) => header + \" from\"`. */\n rangeFrom: (header: string) => string;\n /** The upper bound of a `range` filter: `(header) => header + \" to\"`. */\n rangeTo: (header: string) => string;\n /** The button of the columns menu (\"Columns\"). */\n columns: string;\n /** The button that opens what left the row: `(name) => \"Show more about \" + name`. */\n showMore: (name: string) => string;\n /** The export button (\"Export CSV\"). */\n export: string;\n /** The words of the pagination under the table. */\n pagination?: Partial<PaginationLabels>;\n};\n\nexport const dataTableLabels: DataTableLabels = {\n selectAll: \"Select all rows\",\n selectRow: (name) => `Select ${name}`,\n loading: \"Loading\",\n empty: \"Nothing to show\",\n details: \"Details\",\n expandRow: (name) => `Show details of ${name}`,\n group: (value, count) => `${value}, ${count} ${count === 1 ? \"row\" : \"rows\"}`,\n resize: (header) => `Resize ${header}`,\n results: (count) => `${count.toLocaleString(\"en\")} ${count === 1 ? \"row\" : \"rows\"}`,\n filters: \"Filter the table\",\n clearFilters: \"Clear filters\",\n removeFilter: (label) => `Remove ${label}`,\n activeFilter: (header, value) => `${header}: ${value}`,\n search: (header) => `Search ${header.toLocaleLowerCase()}`,\n rangeFrom: (header) => `${header} from`,\n rangeTo: (header) => `${header} to`,\n columns: \"Columns\",\n showMore: (name) => `Show more about ${name}`,\n export: \"Export CSV\",\n};\n\nexport type DataTableProps<T> = {\n /** The rows (stable: module scope, state or a query's data). Sorted, filtered and paginated here unless `manual`. */\n rows: readonly T[];\n /** The columns, in order (stable: module scope or `useMemo`). */\n columns: readonly DataTableColumn<T>[];\n /** A stable id per row: the React key, the selection's value, the expansion's key. */\n getRowId: (row: T) => string;\n /** What the table lists (\"Jobs\", \"Your videos\"): its `<caption>`, hidden unless `showCaption`. */\n caption: string;\n /** Shows the caption above the table. */\n showCaption?: boolean;\n\n /** The sorted column (controlled), `null` for none. */\n sort?: DataTableSort;\n /** The sort at first, uncontrolled. */\n defaultSort?: DataTableSort;\n /** Called when a header asks for a new sort. */\n onSortChange?: (sort: DataTableSort) => void;\n\n /** The filters in force (controlled), by column id — what `DataTableFilters` edits. */\n filters?: DataTableFilterState;\n /** The filters at first, uncontrolled. */\n defaultFilters?: DataTableFilterState;\n /** Called with the new filters. */\n onFiltersChange?: (filters: DataTableFilterState) => void;\n\n /**\n * Keeps the sort, the filters and the page in the address (`?clients.sort=…&clients.page=2`): back and forward, a reload\n * and a shared link all land on the same table. Replaces `sort`, `filters` and `page`; needs the router's adapter\n * (`RouteStateProvider`) in a framework.\n */\n routeKey?: string;\n\n /** Adds a checkbox per row and one in the header. */\n selectable?: boolean;\n /** The ids selected (controlled). */\n selected?: readonly string[];\n /** The ids selected at first, uncontrolled. */\n defaultSelected?: readonly string[];\n /** Called with the new selection. */\n onSelectedChange?: (selected: string[]) => void;\n /** The name of a row in its labels (checkbox, expand button). Default: its id. */\n rowLabel?: (row: T) => string;\n\n /** The columns the rows are grouped by, in order (controlled) — each `groupable`. */\n groupBy?: readonly string[];\n /** The grouping at first, uncontrolled. */\n defaultGroupBy?: readonly string[];\n /** Called with the new grouping. */\n onGroupByChange?: (groupBy: string[]) => void;\n\n /** Visible (`true`) or hidden (`false`) columns, by id (controlled); a column not listed is visible. */\n columnVisibility?: Readonly<Record<string, boolean>>;\n /** The visibility at first, uncontrolled. */\n defaultColumnVisibility?: Readonly<Record<string, boolean>>;\n /** Called with the new visibility (`DataTableColumnsMenu`). */\n onColumnVisibilityChange?: (visibility: Record<string, boolean>) => void;\n\n /** Columns that stay in view while the table scrolls sideways: at the start (a name) or the end (actions). */\n pinning?: { start?: readonly string[]; end?: readonly string[] };\n /** Columns can be resized (pointer drag, or the arrow keys on the focused handle). */\n resizing?: boolean;\n\n /** The children of a row (a tree): each row with children gets a button that shows them. */\n getSubRows?: (row: T) => readonly T[] | undefined;\n /** A panel under an opened row (the details of a job): each row gets a button that opens it. */\n renderDetail?: (row: T) => React.ReactNode;\n /** The opened rows and groups (controlled), by id. */\n expanded?: Readonly<Record<string, boolean>>;\n /** The opened rows at first, uncontrolled. */\n defaultExpanded?: Readonly<Record<string, boolean>>;\n /** Called with the opened rows. */\n onExpandedChange?: (expanded: Record<string, boolean>) => void;\n\n /** Rows per page (controlled): turns on the pagination under the table. */\n pageSize?: number;\n /** Rows per page at first, uncontrolled: turns on the pagination under the table. */\n defaultPageSize?: number;\n /** Called with the size chosen in the pagination's select (`pageSizeOptions`). */\n onPageSizeChange?: (pageSize: number) => void;\n /** The sizes the pagination offers (`[10, 25, 50]`). */\n pageSizeOptions?: readonly number[];\n /** The page, from 1 (controlled). */\n page?: number;\n /** The page at first, uncontrolled. Default 1. */\n defaultPage?: number;\n /** Called with the page asked for. */\n onPageChange?: (page: number) => void;\n\n /** The server does the work: the rows are shown as given (sorted, filtered, a single page) — fetch in `onStateChange`. */\n manual?: { sorting?: boolean; filtering?: boolean; pagination?: boolean };\n /** The number of rows on the server (`manual.pagination`): the page count and the results' count. */\n rowCount?: number;\n /** Called with the sort, the filters and the page after each change: the query key of a server table. */\n onStateChange?: (query: DataTableQuery) => void;\n\n /** Rows are loading: skeleton rows (`loadingRows` of them) and `aria-busy`. */\n loading?: boolean;\n /** How many skeleton rows while loading. Default 5. */\n loadingRows?: number;\n /** A failure, shown in place of the rows (an `Alert`, a retry button); announced. */\n error?: React.ReactNode;\n /** Shown when there is no row (an `EmptyState`). Default: `labels.empty`. */\n empty?: React.ReactNode;\n\n /** `auto` (default): a table, cards below 36rem of container width. `table` or `cards` to force one. */\n layout?: \"auto\" | \"table\" | \"cards\";\n /**\n * What a row becomes on a phone (under 36 rem, or always with `layout=\"cards\"`): `cards` (a card per row, its values\n * labelled) or `list` — a list row: the selection's checkbox, the `title` column with its `priority: 2` columns joined as\n * one line of facts, the `status` / `badge` column at the end; the other columns in the row's detail.\n * @default \"cards\"\n */\n phone?: \"cards\" | \"list\";\n /** comfortable (default) · compact — one row height per density. */\n density?: \"comfortable\" | \"compact\";\n /** The header stays at the top of the window while the page scrolls (`--dt-top` on the table, or a number of px, clears a fixed bar). */\n stickyHeader?: boolean | number;\n /** Zebra rows. */\n striped?: boolean;\n /**\n * The table never scrolls sideways by default once its columns have a `type` or a `priority`: what does not fit goes to\n * the row's detail, then to cards. `true` opts in to a sideways scroll instead, with fades at the edges.\n */\n scroll?: boolean;\n /** Keeps the first column in view while the table scrolls sideways (with `scroll`). */\n stickyFirstColumn?: boolean;\n /** Renders only the rows in view, in a scrolling body of `height` px; rows are measured (`estimateRowHeight` is a guess). Forces the table layout. */\n virtualized?: { height: number; estimateRowHeight?: number; overscan?: number };\n\n /** Above the table, inside its frame: `DataTableFilters`, `DataTableColumnsMenu`, `DataTableExport`, actions. */\n toolbar?: React.ReactNode;\n /** Under the table (after the pagination): a total, a note. */\n footer?: React.ReactNode;\n /** The words, passed translated; English by default. */\n labels?: Partial<DataTableLabels>;\n /** Classes merged on the root. */\n className?: string;\n};\n\ntype Context = {\n table: DataTableInstance<object>;\n columns: readonly DataTableColumn<object>[];\n labels: DataTableLabels;\n filters: DataTableFilterState;\n setFilters: (filters: DataTableFilterState) => void;\n /** The rows after the filters (all pages), or the server's count. */\n resultCount: number;\n /** The rows to export: filtered and sorted, every page, without the group rows. */\n exportRows: () => readonly unknown[];\n manualFiltering: boolean;\n};\n\nconst DataTableContext = React.createContext<Context | null>(null);\n\n/**\n * The table a component sits in (`toolbar`, or anything under it): the TanStack Table instance (`table` — the escape\n * hatch for what the props do not cover), the columns, the words, the filters and their setter.\n */\nexport function useDataTable<T extends RowData = object>() {\n const context = React.useContext(DataTableContext);\n if (!context) throw new Error(\"useDataTable: call it inside a DataTable (its `toolbar`, `footer` or a cell)\");\n return context as unknown as Omit<Context, \"table\" | \"columns\" | \"exportRows\"> & {\n table: DataTableInstance<T>;\n columns: readonly DataTableColumn<T>[];\n exportRows: () => readonly T[];\n };\n}\n\n// A card never scrolls sideways, even when untyped columns keep the table's scroller.\nconst CARD_CLIP = { auto: \"@max-xl:overflow-x-clip!\", table: undefined, cards: \"overflow-x-clip!\" } as const;\nconst TRUNCATE = { auto: \"@xl:truncate\", table: \"truncate\", cards: \"\" } as const;\nconst MIN = { auto: \"@xl:min-w-(--dt-min)!\", table: \"min-w-(--dt-min)!\", cards: \"\" } as const;\nconst MAX = { auto: \"@xl:max-w-(--dt-max)!\", table: \"max-w-(--dt-max)!\", cards: \"\" } as const;\n// A sideways scroll asked for (`scroll`): the edges fade where there is more to see.\nconst SHADOWS =\n \"[background:linear-gradient(to_right,var(--kz-surface-1),transparent)_left/24px_100%_no-repeat_local,linear-gradient(to_left,var(--kz-surface-1),transparent)_right/24px_100%_no-repeat_local,linear-gradient(to_right,rgb(0_0_0/0.18),transparent)_left/10px_100%_no-repeat_scroll,linear-gradient(to_left,rgb(0_0_0/0.18),transparent)_right/10px_100%_no-repeat_scroll]\";\nconst ALIGN = { start: \"text-left\", center: \"text-center\", end: \"text-right\" } as const;\nconst NONE: readonly never[] = [];\nconst NO_RECORD: Readonly<Record<string, never>> = {};\nconst apply = <S,>(updater: S | ((old: S) => S), old: S): S => (typeof updater === \"function\" ? (updater as (old: S) => S)(old) : updater);\n\nconst valueOf = <T,>(column: DataTableColumn<T>, row: T): CellValue =>\n column.value ? column.value(row) : ((row as Record<string, unknown>)[column.id] as CellValue);\n\nconst display = (value: CellValue) => (value instanceof Date ? value.toISOString() : String(value ?? \"\"));\n\n/** A table of records — sort, filters and facets, groups, details, pages, selection, visibility, pinning, resizing — on the client or the server, cards on a phone, windowing for long lists. */\nexport function DataTable<T extends RowData>({\n rows,\n columns,\n getRowId,\n caption,\n showCaption,\n sort: sortProp,\n routeKey,\n defaultSort = null,\n onSortChange,\n filters: filtersProp,\n defaultFilters = NO_RECORD,\n onFiltersChange,\n selectable,\n selected: selectedProp,\n defaultSelected = NONE,\n onSelectedChange,\n rowLabel,\n groupBy: groupByProp,\n defaultGroupBy = NONE,\n onGroupByChange,\n columnVisibility: visibilityProp,\n defaultColumnVisibility = NO_RECORD,\n onColumnVisibilityChange,\n pinning,\n resizing,\n getSubRows,\n renderDetail,\n expanded: expandedProp,\n defaultExpanded = NO_RECORD,\n onExpandedChange,\n pageSize: pageSizeProp,\n defaultPageSize,\n onPageSizeChange,\n pageSizeOptions,\n page: pageProp,\n defaultPage = 1,\n onPageChange,\n manual,\n rowCount,\n onStateChange,\n loading,\n loadingRows = 5,\n error,\n empty,\n layout = \"auto\",\n phone = \"cards\",\n density,\n stickyHeader,\n striped,\n scroll,\n stickyFirstColumn,\n virtualized,\n toolbar,\n footer,\n labels: given,\n className,\n}: DataTableProps<T>) {\n const labels = { ...dataTableLabels, ...given };\n const effectiveLayout = virtualized ? \"table\" : layout;\n const L = effectiveLayout;\n const typed = columns.some((c) => c.type || c.priority);\n const list = phone === \"list\" && L !== \"table\";\n const s = dataTable({ layout: L, density, sticky: Boolean(stickyHeader), striped: Boolean(striped), typed, phone: list ? \"list\" : \"cards\" });\n\n const route = useRouteTable(routeKey, { sort: defaultSort, page: defaultPage, filters: defaultFilters }, columns.map((c) => c.id));\n const [sort, setSort] = useControllable<DataTableSort>(route ? route.sort : sortProp, defaultSort, route?.onSortChange ?? onSortChange);\n const [filters, setFiltersState] = useControllable<DataTableFilterState>(route ? route.filters : filtersProp, defaultFilters, route?.onFiltersChange ?? onFiltersChange);\n const [selected, setSelected] = useControllable<readonly string[]>(selectedProp, defaultSelected, onSelectedChange as (next: readonly string[]) => void);\n const [groupBy, setGroupBy] = useControllable<readonly string[]>(groupByProp, defaultGroupBy, onGroupByChange as (next: readonly string[]) => void);\n const [visibility, setVisibility] = useControllable<Readonly<Record<string, boolean>>>(visibilityProp, defaultColumnVisibility, onColumnVisibilityChange as (next: Readonly<Record<string, boolean>>) => void);\n const [expanded, setExpanded] = useControllable<Readonly<Record<string, boolean>>>(expandedProp, defaultExpanded, onExpandedChange as (next: Readonly<Record<string, boolean>>) => void);\n const paginated = pageSizeProp !== undefined || defaultPageSize !== undefined;\n const [pageSize, setPageSize] = useControllable<number>(pageSizeProp, defaultPageSize ?? Number.POSITIVE_INFINITY, onPageSizeChange);\n const [page, setPage] = useControllable<number>(route ? route.page : pageProp, defaultPage, route?.onPageChange ?? onPageChange);\n const [sizing, setSizing] = React.useState<Record<string, number>>({});\n const [resizeState, setResizeState] = React.useState<ColumnResizingState | undefined>(undefined);\n\n const announced = React.useRef(JSON.stringify([defaultSort, defaultFilters, paginated ? defaultPage : 1, paginated ? pageSize : null]));\n // One place announces the server's query: after any change of sort, filters, page or page size.\n const announce = (next: Partial<DataTableQuery>) => {\n const query = { sort, filters, page: paginated ? page : 1, pageSize: paginated ? pageSize : Number.POSITIVE_INFINITY, ...next };\n if (route) announced.current = JSON.stringify([query.sort, query.filters, query.page, paginated ? query.pageSize : null]);\n onStateChange?.(query);\n };\n // In the address (routeKey), the sort or the filters reset the page in the same navigation: no second write.\n const changeSort = (next: DataTableSort) => {\n setSort(next);\n if (paginated && page !== 1 && !route) setPage(1);\n announce({ sort: next, page: 1 });\n };\n const changeFilters = (next: DataTableFilterState) => {\n setFiltersState(next);\n if (paginated && page !== 1 && !route) setPage(1);\n announce({ filters: next, page: 1 });\n };\n // The address can change under the table (back, forward, a shared link): the server is told the query it now shows,\n // once — a change the table made itself was announced already. A first visit on the defaults says nothing.\n const routeQuery = route ? JSON.stringify([route.sort, route.filters, paginated ? route.page : 1, paginated ? pageSize : null]) : null;\n React.useEffect(() => {\n if (routeQuery === null || routeQuery === announced.current) return;\n announced.current = routeQuery;\n announce({});\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only a change of the address's query announces\n }, [routeQuery]);\n const changePage = (next: number) => {\n setPage(next);\n announce({ page: next });\n };\n const changePageSize = (next: number) => {\n setPageSize(next);\n setPage(1);\n announce({ pageSize: next, page: 1 });\n };\n\n const hasExpander = Boolean(renderDetail || getSubRows);\n // Columns that can leave the row: their lines go to the row's detail, opened by a chevron in the first cell.\n const priorityOf = (column: DataTableColumn<T>): 1 | Priority => (column.priority && column.priority > 1 ? (column.priority as Priority) : 1);\n const maxPriority = columns.reduce<1 | Priority>((max, column) => (priorityOf(column) > max ? priorityOf(column) : max), 1);\n // The list rows' places: the title (the `title` column, else the first), the status at the end, the facts (the 2s) under\n // the title, and the rest away, in the row's detail.\n const titleColumn = columns.find((c) => c.card === \"title\" || (!c.card && c.type === \"title\")) ?? columns[0];\n const placeOf = (column: DataTableColumn<T>): \"title\" | \"status\" | \"facts\" | \"away\" | \"hidden\" => {\n if (column.card === \"hidden\") return \"hidden\";\n if (column === titleColumn) return \"title\";\n if (column.type === \"status\" || column.type === \"badge\") return \"status\";\n return priorityOf(column) === 2 ? \"facts\" : \"away\";\n };\n const listAway = list ? columns.filter((c) => placeOf(c) === \"away\" && priorityOf(c) === 1) : [];\n const facts = list ? columns.filter((c) => placeOf(c) === \"facts\") : [];\n const inlineToggle = (maxPriority > 1 || listAway.length > 0) && !hasExpander;\n const detailed = Boolean(renderDetail) || inlineToggle;\n const defs = React.useMemo<ColumnDef<typeof features, T>[]>(\n () =>\n columns.map((column) => ({\n id: column.id,\n accessorFn: (row: T) => valueOf(column, row),\n header: column.header,\n enableSorting: Boolean(column.sortable),\n sortFn: sortByValue as never,\n sortUndefined: \"last\",\n enableColumnFilter: Boolean(column.filter),\n filterFn: (column.filter ? FILTERS[column.filter] : FILTERS.text) as never,\n enableGrouping: Boolean(column.groupable),\n enableHiding: column.hideable !== false,\n enableResizing: Boolean(resizing),\n ...(column.width ? { size: column.width } : {}),\n minSize: column.minWidth ?? 64,\n })),\n [columns, resizing],\n );\n\n const firstId = columns[0]?.id;\n const pinned = stickyFirstColumn && firstId && !pinning?.start?.length ? { ...pinning, start: [firstId] } : pinning;\n const pageIndex = Math.max(0, page - 1);\n const table = useTable<typeof features, T>({\n features,\n columns: defs,\n data: rows as T[],\n getRowId: (row) => getRowId(row),\n getSubRows: getSubRows ? (row) => getSubRows(row) as T[] | undefined : undefined,\n getRowCanExpand: detailed ? () => true : undefined,\n state: {\n sorting: sort ? [{ id: sort.column, desc: sort.direction === \"descending\" }] : [],\n columnFilters: Object.entries(filters).map(([id, value]) => ({ id, value })),\n rowSelection: Object.fromEntries(selected.map((id) => [id, true])),\n grouping: [...groupBy],\n columnVisibility: { ...visibility },\n expanded: { ...expanded },\n pagination: { pageIndex, pageSize: paginated ? pageSize : Math.max(1, rows.length) },\n columnPinning: { start: [...(pinned?.start ?? [])], end: [...(pinned?.end ?? [])] },\n columnSizing: sizing,\n ...(resizeState ? { columnResizing: resizeState } : {}),\n },\n onSortingChange: (updater) => {\n const [first] = apply(updater, sort ? [{ id: sort.column, desc: sort.direction === \"descending\" }] : []);\n changeSort(first ? { column: first.id, direction: first.desc ? \"descending\" : \"ascending\" } : null);\n },\n onColumnFiltersChange: (updater) => {\n const next = apply(updater, Object.entries(filters).map(([id, value]) => ({ id, value })));\n changeFilters(Object.fromEntries(next.map((f) => [f.id, f.value as FilterValue])));\n },\n onRowSelectionChange: (updater) => {\n const next = apply(updater, Object.fromEntries(selected.map((id) => [id, true])));\n setSelected(Object.keys(next).filter((id) => next[id]));\n },\n onGroupingChange: (updater) => setGroupBy(apply(updater, [...groupBy])),\n onColumnVisibilityChange: (updater) => setVisibility(apply(updater, { ...visibility })),\n onExpandedChange: (updater) => {\n const next = apply(updater, { ...expanded });\n setExpanded(next === true ? Object.fromEntries(table.getRowModel().rows.map((r) => [r.id, true])) : next);\n },\n onColumnSizingChange: (updater) => setSizing((old: Record<string, number>) => apply(updater, old)),\n onColumnResizingChange: (updater) => setResizeState((old) => apply(updater, old as ColumnResizingState)),\n enableSortingRemoval: true,\n sortDescFirst: false,\n manualSorting: manual?.sorting,\n manualFiltering: manual?.filtering,\n manualPagination: manual?.pagination || !paginated,\n rowCount: manual?.pagination ? rowCount : undefined,\n autoResetPageIndex: false,\n autoResetExpanded: false,\n groupedColumnMode: false,\n columnResizeMode: \"onChange\",\n enableRowSelection: (row) => !row.getIsGrouped(),\n });\n\n const visibleColumns = table.getVisibleLeafColumns();\n const byId = new Map(columns.map((c) => [c.id, c]));\n const pageRows = table.getRowModel().rows;\n const leafCount = (manual?.pagination || manual?.filtering) && rowCount !== undefined ? rowCount : table.getFilteredRowModel().rows.length;\n const pageCount = paginated ? Math.max(1, manual?.pagination ? Math.ceil((rowCount ?? rows.length) / pageSize) : table.getPageCount()) : 1;\n // A page beyond the last (the filters shrank the list): show the last one.\n React.useEffect(() => {\n if (paginated && !loading && page > pageCount) changePage(pageCount);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only when the count of pages drops under the page\n }, [pageCount]);\n\n const selectableIds = pageRows.filter((r) => !r.getIsGrouped()).map((r) => r.id);\n const chosen = new Set(selected);\n const allChosen = selectableIds.length > 0 && selectableIds.every((id) => chosen.has(id));\n const someChosen = selectableIds.some((id) => chosen.has(id));\n const toggleAll = () =>\n setSelected(allChosen ? selected.filter((id) => !selectableIds.includes(id)) : [...new Set([...selected, ...selectableIds])]);\n\n const span = visibleColumns.length + (selectable ? 1 : 0) + (hasExpander ? 1 : 0);\n const fixedLayout = Boolean(resizing || pinned?.start?.length || pinned?.end?.length);\n const sideways = scroll ?? (!typed && !stickyHeader);\n const nameOf = (row: TableRow<T>) => (rowLabel ? rowLabel(row.original) : row.id);\n\n // Windowing: the rows in view, between two spacer rows that keep the scroll height.\n const scroller = React.useRef<HTMLDivElement>(null);\n const fallbacks = useLayoutFallbacks(virtualized?.height ?? 0, virtualized?.estimateRowHeight ?? 44);\n const virtualizer = useVirtualizer({\n ...fallbacks,\n count: pageRows.length,\n getScrollElement: () => scroller.current,\n estimateSize: () => virtualized?.estimateRowHeight ?? 44,\n overscan: virtualized?.overscan ?? 6,\n initialRect: { width: 0, height: virtualized?.height ?? 0 },\n getItemKey: (index) => pageRows[index]?.id ?? index,\n enabled: Boolean(virtualized) && !loading,\n });\n const windowItems = virtualized && !loading ? virtualizer.getVirtualItems() : null;\n const before = windowItems?.[0]?.start ?? 0;\n const after = windowItems && windowItems.length > 0 ? virtualizer.getTotalSize() - (windowItems.at(-1)?.end ?? 0) : 0;\n\n const pin = (column: TableColumn<T>): { \"data-pin\"?: \"start\" | \"end\"; style?: React.CSSProperties } => {\n const position = column.getIsPinned();\n if (!position) return {};\n const offset = position === \"start\" ? column.getStart(\"start\") : column.getAfter(\"end\");\n return { \"data-pin\": position, style: { [\"--dt-pin\" as string]: `${offset}px` } };\n };\n const width = (column: TableColumn<T>): React.CSSProperties | undefined =>\n fixedLayout || byId.get(column.id)?.width ? { width: column.getSize() } : undefined;\n\n const message = (content: React.ReactNode, alert?: boolean) => (\n <tr role=\"row\" className={s.tr({ className: \"hover:bg-transparent\" })}>\n <td role=\"cell\" colSpan={span} data-card=\"message\" className={s.td({ className: s.message() })}>\n {alert ? <div role=\"alert\">{content}</div> : content}\n </td>\n </tr>\n );\n\n const cardOf = (column: DataTableColumn<T> | undefined) =>\n column?.card === \"title\" || (column && !column.card && column.type === \"title\") ? \"title\" : column?.card === \"hidden\" ? \"hidden\" : undefined;\n\n // What a cell shows: the column's `cell`, or its value by type.\n const contentOf = (column: DataTableColumn<T>, original: T): React.ReactNode => {\n if (column.cell) return column.cell(original);\n const value = valueOf(column, original);\n const text = column.type === \"date\" && value instanceof Date ? value.toISOString().slice(0, 10) : display(value);\n const cut = TRUNCATE[L];\n switch (column.type) {\n case \"title\": {\n const sub = column.subtitle?.(original);\n const href = column.href?.(original);\n return (\n <span className=\"block min-w-0\">\n {href ? (\n <a href={href} className={cn(\"block font-semibold text-fg no-underline hover:underline focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\", cut, list && LIST_LINK[L])} title={text}>\n {text}\n </a>\n ) : (\n <span className={cn(\"block font-semibold text-fg\", cut)} title={text}>\n {text}\n </span>\n )}\n {sub ? <span className={cn(\"block font-mono text-xs text-fg-tertiary\", cut)}>{sub}</span> : null}\n </span>\n );\n }\n case \"number\":\n return (\n <span>\n {typeof value === \"number\" ? value.toLocaleString(\"en\") : text}\n {column.unit ? <span className=\"ms-1 text-fg-secondary\">{column.unit}</span> : null}\n </span>\n );\n case \"link\": {\n const href = column.href?.(original);\n return href ? (\n <a href={href} title={text} className={cn(\"block text-fg-accent underline-offset-2 hover:underline\", cut)}>\n {text}\n </a>\n ) : (\n <span className={cn(\"block\", cut)} title={text}>\n {text}\n </span>\n );\n }\n default: {\n const lines = column.clamp ?? (column.type === \"text\" ? 2 : undefined);\n if (!column.nowrap && !lines) return text;\n return (\n <span className={column.nowrap ? cn(\"block\", cut || \"truncate\") : CLAMP[lines as 1 | 2 | 3]} title={text}>\n {text}\n </span>\n );\n }\n }\n };\n\n // A group's row keeps its value as the title and its aggregates; a facts column is away (its value is in the title's line).\n const listPlace = (row: TableRow<T> | null, column: DataTableColumn<T>) => {\n if (row?.getIsGrouped()) return row.groupingColumnId === column.id ? \"title\" : column.aggregate ? \"status\" : \"away\";\n const place = placeOf(column);\n return place === \"facts\" || place === \"hidden\" ? \"away\" : place;\n };\n\n const dataCell = (row: TableRow<T>, cell: TableCell<T>, first: boolean) => {\n const column = byId.get(cell.column.id);\n if (!column) return null;\n const { style, ...pinnedProps } = pin(cell.column);\n let content: React.ReactNode;\n if (row.getIsGrouped()) {\n const leaves = row.getLeafRows().filter((r) => !r.getIsGrouped()).map((r) => r.original);\n if (cell.column.id === row.groupingColumnId) {\n const value = display(row.groupingValue as CellValue);\n content = (\n <button type=\"button\" className={s.toggle({ className: \"px-1.5 font-semibold text-fg\" })} aria-expanded={row.getIsExpanded()} onClick={row.getToggleExpandedHandler()}>\n <ChevronGlyph direction=\"right\" className=\"h-4 w-4\" />\n {labels.group(value, leaves.length)}\n </button>\n );\n } else content = column.aggregate ? column.aggregate(leaves) : null;\n } else {\n content = contentOf(column, row.original);\n if (list && column === titleColumn && facts.length > 0) {\n content = (\n <span className=\"block min-w-0\">\n {content}\n <span data-facts=\"\" className={LIST_FACTS[L]}>\n {facts.map((c, i) => (\n <React.Fragment key={c.id}>\n {i > 0 ? <span aria-hidden>{\" · \"}</span> : null}\n {contentOf(c, row.original)}\n </React.Fragment>\n ))}\n </span>\n </span>\n );\n }\n if (first && inlineToggle) {\n content = (\n <span className=\"flex min-w-0 items-center gap-1\">\n <button\n type=\"button\"\n className={s.toggle({ className: cn(maxPriority > 1 ? TOGGLE[L][maxPriority as Priority] : \"hidden\", listAway.length > 0 && LIST_TOGGLE[L], list && \"relative z-[1]\") })}\n aria-expanded={row.getIsExpanded()}\n aria-label={labels.showMore(nameOf(row))}\n onClick={row.getToggleExpandedHandler()}\n >\n <ChevronGlyph direction=\"right\" className=\"h-4 w-4\" />\n </button>\n <span className=\"min-w-0 flex-1\">{content}</span>\n </span>\n );\n }\n }\n const level = priorityOf(column);\n const type = column.type;\n const cellClass = [\n ALIGN[column.align ?? (type === \"number\" ? \"end\" : \"start\")],\n type ? TYPE_CELL[type][L] : \"\",\n level > 1 ? LEAVES[L][level as Priority] : \"\",\n (type || column.priority) && column.minWidth !== undefined ? MIN[L] : \"\",\n column.maxWidth !== undefined ? MAX[L] : \"\",\n ].join(\" \");\n return (\n <td\n role=\"cell\"\n key={cell.id}\n data-label={column.header}\n data-card={list ? (placeOf(column) === \"hidden\" ? \"hidden\" : undefined) : row.getIsGrouped() ? (cell.column.id === row.groupingColumnId ? \"title\" : column.aggregate ? undefined : \"hidden\") : cardOf(column)}\n data-list={list ? listPlace(row, column) : undefined}\n {...pinnedProps}\n className={s.td({ className: cellClass })}\n style={{\n ...style,\n ...(column.minWidth !== undefined ? { [\"--dt-min\" as string]: `${column.minWidth}px` } : {}),\n ...(column.maxWidth !== undefined ? { [\"--dt-max\" as string]: `${column.maxWidth}px` } : {}),\n ...(first && row.depth > 0 && !row.getIsGrouped() ? { paddingInlineStart: `${1 + row.depth * 1.25}rem` } : {}),\n }}\n >\n {content}\n </td>\n );\n };\n\n const renderRow = (row: TableRow<T>, index: number) => {\n const isChosen = chosen.has(row.id);\n const grouped = row.getIsGrouped();\n const canExpand = !grouped && (renderDetail ? true : row.getCanExpand());\n const showDetail = detailed && !grouped && row.getIsExpanded() && !virtualized;\n const cells = row.getVisibleCells();\n const main = (\n <tr\n role=\"row\"\n data-index={windowItems ? index : undefined}\n ref={windowItems ? virtualizer.measureElement : undefined}\n aria-rowindex={virtualized ? index + 2 : undefined}\n data-state={isChosen ? \"selected\" : undefined}\n data-group={grouped ? \"\" : undefined}\n className={s.tr({ className: grouped ? s.groupRow() : undefined })}\n >\n {selectable && (\n <td role=\"cell\" className={s.td({ className: s.select() })}>\n {grouped ? null : <Checkbox checked={isChosen} onCheckedChange={() => row.toggleSelected()} aria-label={labels.selectRow(nameOf(row))} />}\n </td>\n )}\n {hasExpander && (\n <td role=\"cell\" className={s.td({ className: s.expander() })}>\n {canExpand ? (\n <button type=\"button\" className={s.toggle()} aria-expanded={row.getIsExpanded()} aria-label={labels.expandRow(nameOf(row))} onClick={row.getToggleExpandedHandler()}>\n <ChevronGlyph direction=\"right\" className=\"h-4 w-4\" />\n </button>\n ) : null}\n </td>\n )}\n {cells.map((cell, i) => dataCell(row, cell, i === 0))}\n </tr>\n );\n // One Fragment keyed by the row either way: opening a row keeps its button (and the focus on it).\n if (!showDetail) return <React.Fragment key={row.id}>{main}</React.Fragment>;\n const left = visibleColumns.filter((c) => {\n const column = byId.get(c.id) as DataTableColumn<T>;\n return priorityOf(column) > 1 || listAway.includes(column);\n });\n return (\n <React.Fragment key={row.id}>\n {main}\n <tr role=\"row\" className={s.tr({ className: \"hover:bg-transparent\" })}>\n <td role=\"cell\" colSpan={span} data-card=\"message\" className={s.td({ className: renderDetail ? s.detail() : \"bg-surface-0 p-0 text-left\" })}>\n {left.length > 0 ? (\n <dl className={cn(\"m-0 grid gap-3 text-left\", renderDetail ? \"mb-4\" : cn(\"px-4 py-4\", maxPriority > 1 ? PANEL[L][maxPriority as Priority] : \"hidden\", listAway.length > 0 && LIST_PANEL[L]))}>\n {left.map((c) => {\n const column = byId.get(c.id) as DataTableColumn<T>;\n return (\n <div key={c.id} className={cn(listAway.includes(column) ? LIST_IN_DETAIL[L] : IN_DETAIL[L][priorityOf(column) as Priority], \"grid-cols-[minmax(5rem,8rem)_minmax(0,1fr)] items-baseline gap-3\")}>\n <dt className=\"text-xs font-semibold text-fg-secondary\">{column.header}</dt>\n <dd className=\"m-0 min-w-0 text-sm text-fg\">{contentOf(column, row.original)}</dd>\n </div>\n );\n })}\n </dl>\n ) : null}\n {renderDetail ? renderDetail(row.original) : null}\n </td>\n </tr>\n </React.Fragment>\n );\n };\n\n let body: React.ReactNode;\n if (loading) {\n body = Array.from({ length: loadingRows }, (_, i) => (\n <tr role=\"row\" key={`loading-${i}`} aria-hidden className={s.tr()}>\n {selectable && <td role=\"cell\" className={s.td({ className: s.select() })} />}\n {hasExpander && <td role=\"cell\" className={s.td({ className: s.expander() })} />}\n {visibleColumns.map((column) => (\n <td role=\"cell\" key={column.id} data-card={list ? undefined : cardOf(byId.get(column.id))} data-list={list ? listPlace(null, byId.get(column.id) as DataTableColumn<T>) : undefined} className={s.td()}>\n <div className={s.skeleton()} />\n </td>\n ))}\n </tr>\n ));\n } else if (error) body = message(error, true);\n else if (pageRows.length === 0) body = message(empty ?? labels.empty);\n else if (windowItems) body = windowItems.map((item) => renderRow(pageRows[item.index] as TableRow<T>, item.index));\n else body = pageRows.map((row, i) => renderRow(row, i));\n\n const headers = table.getHeaderGroups().at(-1)?.headers ?? [];\n const tableElement = (\n <table\n role=\"table\"\n aria-busy={loading || undefined}\n aria-rowcount={virtualized ? pageRows.length + 1 : undefined}\n className={s.table({ className: fixedLayout ? \"table-fixed\" : undefined })}\n style={fixedLayout ? { minWidth: table.getTotalSize() + (selectable ? 40 : 0) + (hasExpander ? 40 : 0) } : undefined}\n >\n <caption className={showCaption ? s.caption() : \"sr-only\"}>\n {caption}\n {loading ? <span className=\"sr-only\">{` — ${labels.loading}`}</span> : null}\n </caption>\n <thead role=\"rowgroup\" className={s.thead({ className: virtualized ? \"sticky top-0 z-10 bg-surface-2\" : undefined })}>\n <tr role=\"row\" aria-rowindex={virtualized ? 1 : undefined} className={s.headRow()}>\n {selectable && (\n <th role=\"columnheader\" scope=\"col\" data-keep=\"\" className={s.th({ className: s.select() })}>\n <Checkbox\n checked={allChosen ? true : someChosen ? \"indeterminate\" : false}\n onCheckedChange={toggleAll}\n disabled={loading || selectableIds.length === 0}\n aria-label={labels.selectAll}\n />\n </th>\n )}\n {hasExpander && (\n <th role=\"columnheader\" scope=\"col\" className={s.th({ className: s.expander() })}>\n <span className=\"sr-only\">{labels.details}</span>\n </th>\n )}\n {headers.map((header) => {\n const column = byId.get(header.column.id);\n if (!column) return null;\n const sorted = header.column.getIsSorted();\n const direction: SortDirection | undefined = sorted === \"asc\" ? \"ascending\" : sorted === \"desc\" ? \"descending\" : undefined;\n const { style, ...pinnedProps } = pin(header.column);\n const level = priorityOf(column);\n return (\n <th\n role=\"columnheader\"\n scope=\"col\"\n key={header.id}\n aria-sort={column.sortable ? (direction ?? \"none\") : undefined}\n data-keep={column.sortable ? \"\" : undefined}\n {...pinnedProps}\n className={s.th({ className: cn(ALIGN[column.align ?? (column.type === \"number\" ? \"end\" : \"start\")], level > 1 && LEAVES_HEAD[L][level as Priority]) })}\n style={{ ...style, ...(typeof stickyHeader === \"number\" ? { [\"--dt-top\" as string]: `${stickyHeader}px` } : {}), ...width(header.column) }}\n >\n {column.sortable ? (\n <button type=\"button\" aria-pressed={Boolean(direction)} className={s.sortButton()} onClick={() => header.column.toggleSorting(undefined, false)}>\n {column.header}\n <SortGlyph direction={direction} className=\"h-3.5 w-3.5\" />\n </button>\n ) : column.headerHidden ? (\n <span className=\"sr-only\">{column.header}</span>\n ) : (\n column.header\n )}\n {resizing && header.column.getCanResize() ? (\n <ResizeHandle\n label={labels.resize(column.header)}\n size={header.column.getSize()}\n min={column.minWidth ?? 64}\n resizing={header.column.getIsResizing()}\n className={s.resizer()}\n onPointerStart={header.getResizeHandler()}\n onSize={(size) => setSizing((old: Record<string, number>) => ({ ...old, [header.column.id]: size }))}\n />\n ) : null}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody role=\"rowgroup\" className={s.tbody()}>\n {before > 0 && (\n <tr aria-hidden style={{ height: before }}>\n <td colSpan={span} />\n </tr>\n )}\n {body}\n {after > 0 && (\n <tr aria-hidden style={{ height: after }}>\n <td colSpan={span} />\n </tr>\n )}\n </tbody>\n </table>\n );\n\n const context: Context = {\n table: table as unknown as DataTableInstance<object>,\n columns: columns as readonly DataTableColumn<object>[],\n labels,\n filters,\n setFilters: changeFilters,\n resultCount: leafCount,\n exportRows: () => table.getSortedRowModel().flatRows.filter((r) => !r.getIsGrouped()).map((r) => r.original),\n manualFiltering: Boolean(manual?.filtering),\n };\n\n const pagination = paginated ? (\n <Pagination\n page={Math.min(page, pageCount)}\n pageCount={pageCount}\n onPageChange={changePage}\n pageSize={pageSizeOptions ? pageSize : undefined}\n pageSizeOptions={pageSizeOptions}\n onPageSizeChange={pageSizeOptions ? changePageSize : undefined}\n disabled={loading}\n labels={labels.pagination}\n />\n ) : null;\n\n return (\n <DataTableContext.Provider value={context}>\n <div className={s.root({ className })}>\n {toolbar ? <div className={s.toolbar()}>{toolbar}</div> : null}\n {virtualized ? (\n // A scrolling region the keyboard can reach: Tab lands on it, the arrows scroll it.\n <div\n ref={scroller}\n tabIndex={0}\n role=\"region\"\n aria-label={caption}\n className={s.scroller({ className: \"overflow-y-auto focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\" })}\n style={{ height: virtualized.height }}\n >\n {tableElement}\n </div>\n ) : (\n <div className={s.scroller({ className: sideways ? (scroll ? SHADOWS : CARD_CLIP[L]) : \"overflow-x-clip\" })}>{tableElement}</div>\n )}\n {pagination || footer ? (\n <div className={s.footer({ className: \"flex flex-col gap-3\" })}>\n {pagination}\n {footer}\n </div>\n ) : null}\n </div>\n </DataTableContext.Provider>\n );\n}\n\n/** The handle on a header's edge: drag it, or focus it and use ← → (Shift for larger steps). */\nfunction ResizeHandle({\n label,\n size,\n min,\n resizing,\n className,\n onPointerStart,\n onSize,\n}: {\n label: string;\n size: number;\n min: number;\n resizing: boolean;\n className: string;\n onPointerStart: (event: unknown) => void;\n onSize: (size: number) => void;\n}) {\n return (\n // A focusable separator is interactive (WAI-ARIA \"window splitter\"): its value is the width, the arrows change it.\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={label}\n aria-valuenow={Math.round(size)}\n aria-valuemin={min}\n tabIndex={0}\n data-resizing={resizing ? \"\" : undefined}\n className={className}\n onMouseDown={onPointerStart}\n onTouchStart={onPointerStart}\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n const step = event.shiftKey ? 48 : 16;\n if (event.key === \"ArrowLeft\") onSize(Math.max(min, size - step));\n else if (event.key === \"ArrowRight\") onSize(size + step);\n else return;\n event.preventDefault();\n }}\n />\n );\n}\n","// Server-safe: no hook, no context. A `<nav>` named by `labels.nav`; the current page is `aria-current=\"page\"`.\n// Two modes: pages (`page` + `pageCount`: numbers with ellipses, which fold into \"Page 3 of 12\" in a narrow container)\n// and cursor (`hasPrevious` / `hasNext`: an API that only knows the next and previous pages). Links (`getHref`) when\n// the page lives in the address — the right default for a list a search engine or a shared link should reach — or\n// buttons (`onPageChange`).\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronGlyph } from \"../glyphs\";\n\nexport const pagination = tv({\n slots: {\n root: \"@container flex w-full flex-wrap items-center justify-between gap-3 text-sm\",\n list: \"flex items-center gap-1\",\n pages: \"hidden items-center gap-1 @md:flex\",\n compact: \"px-2 text-xs font-semibold tabular-nums text-fg-secondary @md:hidden\",\n item:\n \"inline-flex h-9 min-w-9 select-none items-center justify-center gap-1.5 rounded-lg px-2.5 text-sm font-semibold tabular-nums text-fg-secondary \" +\n \"transition-colors hover:bg-surface-2 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n \"aria-[current=page]:bg-accent aria-[current=page]:text-on-accent aria-[current=page]:hover:bg-accent \" +\n \"aria-disabled:pointer-events-none aria-disabled:opacity-40 disabled:pointer-events-none disabled:opacity-40\",\n edge: \"border border-border-default bg-surface-1 px-3\",\n ellipsis: \"inline-flex h-9 min-w-6 items-end justify-center pb-2 text-fg-muted\",\n status: \"text-xs text-fg-secondary tabular-nums\",\n size: \"flex items-center gap-2 text-xs text-fg-secondary\",\n select:\n \"h-9 rounded-lg border border-border-default bg-surface-2 px-2 text-sm text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n});\n\nexport type PaginationLabels = {\n /** The accessible name of the navigation (\"Pagination\", \"Pages of results\"). */\n nav: string;\n /** The previous-page control. */\n previous: string;\n /** The next-page control. */\n next: string;\n /** The accessible name of a page number: `(3) => \"Page 3\"`. */\n page: (page: number) => string;\n /** The folded form, in a narrow container: `(3, 12) => \"Page 3 of 12\"`. */\n compact: (page: number, pageCount: number) => string;\n /** The label of the page-size select (\"Rows per page\"). */\n pageSize: string;\n};\n\n/** The English words, for a quick start — pass your translations through `labels`. */\nexport const paginationLabels: PaginationLabels = {\n nav: \"Pagination\",\n previous: \"Previous\",\n next: \"Next\",\n page: (page) => `Page ${page}`,\n compact: (page, count) => `Page ${page} of ${count}`,\n pageSize: \"Rows per page\",\n};\n\n/**\n * The pages to show: the first and last `boundaries`, the current page and its `siblings`, and `\"…\"` where pages are\n * skipped. A gap of a single page shows that page instead of an ellipsis; few pages are all shown.\n */\nexport function pageRange(page: number, pageCount: number, siblings = 1, boundaries = 1): (number | \"…\")[] {\n // Few enough pages to show them all in the room the folded form takes: no ellipsis.\n if (pageCount <= 2 * boundaries + 2 * siblings + 3) return Array.from({ length: Math.max(0, pageCount) }, (_, i) => i + 1);\n const pages = new Set<number>();\n for (let i = 1; i <= Math.min(boundaries, pageCount); i += 1) pages.add(i);\n for (let i = Math.max(1, pageCount - boundaries + 1); i <= pageCount; i += 1) pages.add(i);\n for (let i = Math.max(1, page - siblings); i <= Math.min(pageCount, page + siblings); i += 1) pages.add(i);\n const sorted = [...pages].sort((a, b) => a - b);\n const out: (number | \"…\")[] = [];\n sorted.forEach((n, i) => {\n const prev = sorted[i - 1];\n if (prev !== undefined && n - prev === 2) out.push(prev + 1);\n else if (prev !== undefined && n - prev > 2) out.push(\"…\");\n out.push(n);\n });\n return out;\n}\n\nexport type PaginationProps = Omit<React.ComponentProps<\"nav\">, \"children\"> & {\n /** Pages mode: the current page, from 1. */\n page?: number;\n /** Pages mode: how many pages there are. Without it, the pagination is in cursor mode. */\n pageCount?: number;\n /** Called with the page asked for (buttons). Ignored for the pages `getHref` turns into links. */\n onPageChange?: (page: number) => void;\n /** The address of a page: the pages become links (crawlable, shareable, the state in the URL). */\n getHref?: (page: number) => string;\n /** Cursor mode: whether there is a previous page. */\n hasPrevious?: boolean;\n /** Cursor mode: whether there is a next page. */\n hasNext?: boolean;\n /** Cursor mode: called by the previous control. */\n onPrevious?: () => void;\n /** Cursor mode: called by the next control. */\n onNext?: () => void;\n /** Pages shown on each side of the current one. Default 1. */\n siblings?: number;\n /** Pages always shown at each end. Default 1. */\n boundaries?: number;\n /** A text beside the controls, read as is: \"41–60 of 1,284\", \"12 results\". */\n status?: React.ReactNode;\n /** The page size, with `pageSizeOptions` and `onPageSizeChange`: a select of rows per page. */\n pageSize?: number;\n /** The sizes offered (`[10, 20, 50]`). */\n pageSizeOptions?: readonly number[];\n /** Called with the size chosen. */\n onPageSizeChange?: (size: number) => void;\n /** Disables every control (a page is loading). */\n disabled?: boolean;\n /** The words, passed translated; English by default. */\n labels?: Partial<PaginationLabels>;\n};\n\ntype ItemProps = {\n href?: string;\n onClick?: () => void;\n disabled?: boolean;\n current?: boolean;\n label: string;\n className: string;\n children: React.ReactNode;\n};\n\nfunction Item({ href, onClick, disabled, current, label, className, children }: ItemProps) {\n const common = { \"aria-label\": label, \"aria-current\": current ? (\"page\" as const) : undefined, className };\n if (href && !disabled) {\n return (\n <a href={href} onClick={onClick} {...common}>\n {children}\n </a>\n );\n }\n if (href) {\n return (\n <a role=\"link\" aria-disabled {...common}>\n {children}\n </a>\n );\n }\n return (\n <button type=\"button\" onClick={onClick} disabled={disabled} {...common}>\n {children}\n </button>\n );\n}\n\n/** Moves through a long list: page numbers (folded on a narrow screen) or previous / next on a cursor. */\nexport function Pagination({\n page = 1,\n pageCount,\n onPageChange,\n getHref,\n hasPrevious,\n hasNext,\n onPrevious,\n onNext,\n siblings = 1,\n boundaries = 1,\n status,\n pageSize,\n pageSizeOptions,\n onPageSizeChange,\n disabled,\n labels: given,\n className,\n ...props\n}: PaginationProps) {\n const s = pagination();\n const labels = { ...paginationLabels, ...given };\n const paged = pageCount !== undefined;\n const count = Math.max(1, pageCount ?? 1);\n const current = Math.min(Math.max(1, page), count);\n const canPrevious = paged ? current > 1 : Boolean(hasPrevious);\n const canNext = paged ? current < count : Boolean(hasNext);\n const go = (target: number) => () => onPageChange?.(target);\n const href = (target: number) => (paged && getHref ? getHref(target) : undefined);\n\n return (\n <nav aria-label={labels.nav} className={s.root({ className })} {...props}>\n {status !== undefined || pageSizeOptions ? (\n <div className=\"flex flex-wrap items-center gap-4\">\n {status !== undefined && <p className={s.status()}>{status}</p>}\n {pageSizeOptions && pageSize !== undefined && (\n <label className={s.size()}>\n {labels.pageSize}\n <select\n className={s.select()}\n value={pageSize}\n disabled={disabled}\n onChange={(event) => onPageSizeChange?.(Number(event.target.value))}\n >\n {pageSizeOptions.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n )}\n </div>\n ) : null}\n <ul className={s.list()}>\n <li>\n <Item\n href={href(current - 1)}\n onClick={paged ? go(current - 1) : onPrevious}\n disabled={disabled || !canPrevious}\n label={labels.previous}\n className={s.item({ className: s.edge() })}\n >\n <ChevronGlyph direction=\"left\" />\n <span className=\"hidden @lg:inline\">{labels.previous}</span>\n </Item>\n </li>\n {paged && (\n <>\n <li className={s.pages()}>\n <ul className=\"contents\">\n {pageRange(current, count, siblings, boundaries).map((n, i) =>\n n === \"…\" ? (\n <li key={`gap-${i}`} aria-hidden className={s.ellipsis()}>\n …\n </li>\n ) : (\n <li key={n}>\n <Item href={href(n)} onClick={go(n)} disabled={disabled} current={n === current} label={labels.page(n)} className={s.item()}>\n {n}\n </Item>\n </li>\n ),\n )}\n </ul>\n </li>\n <li className={s.compact()}>\n {labels.compact(current, count)}\n </li>\n </>\n )}\n <li>\n <Item\n href={href(current + 1)}\n onClick={paged ? go(current + 1) : onNext}\n disabled={disabled || !canNext}\n label={labels.next}\n className={s.item({ className: s.edge() })}\n >\n <span className=\"hidden @lg:inline\">{labels.next}</span>\n <ChevronGlyph direction=\"right\" />\n </Item>\n </li>\n </ul>\n </nav>\n );\n}\n","// The engine of DataTable: TanStack Table v9 behind the Krizaka facade (ADR-001 — a product imports\n// `@krizaka/ui/data-table`, never `@tanstack/*`). The features are registered once, at module scope (stable input),\n// and the Krizaka API (`sort`, `filters`, `selected`, `page`… in the app's words) is translated to TanStack's state\n// here — nothing else of the component knows TanStack's shapes.\nimport {\n type Cell,\n type Column,\n type ColumnDef,\n columnFacetingFeature,\n columnFilteringFeature,\n columnGroupingFeature,\n columnPinningFeature,\n columnResizingFeature,\n type columnResizingState as ColumnResizingState,\n columnSizingFeature,\n columnVisibilityFeature,\n createExpandedRowModel,\n createFacetedMinMaxValues,\n createFacetedRowModel,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createGroupedRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n type FilterFn,\n type ReactTable,\n type Row,\n type RowData,\n rowExpandingFeature,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n type SortFn,\n tableFeatures,\n} from \"@tanstack/react-table\";\n\nexport const features = tableFeatures({\n columnFilteringFeature,\n filteredRowModel: createFilteredRowModel(),\n columnFacetingFeature,\n facetedRowModel: createFacetedRowModel(),\n facetedUniqueValues: createFacetedUniqueValues(),\n facetedMinMaxValues: createFacetedMinMaxValues(),\n columnGroupingFeature,\n groupedRowModel: createGroupedRowModel(),\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n rowExpandingFeature,\n expandedRowModel: createExpandedRowModel(),\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n columnVisibilityFeature,\n columnPinningFeature,\n columnSizingFeature,\n columnResizingFeature,\n});\n\nexport type Features = typeof features;\n/** The TanStack Table instance behind a DataTable — the escape hatch of `useDataTable()`. */\nexport type DataTableInstance<T extends RowData> = ReactTable<Features, T>;\nexport type TableRow<T extends RowData> = Row<Features, T>;\nexport type TableCell<T extends RowData> = Cell<Features, T, unknown>;\nexport type TableColumn<T extends RowData> = Column<Features, T, unknown>;\n\n/** What a cell holds for sorting, filtering and the CSV export: a string, a number, a date, a boolean, or nothing. */\nexport type CellValue = string | number | boolean | Date | null | undefined;\n\n/** A filter's value: a text (`text`), the values chosen (`facet`), or bounds, either open (`range`). */\nexport type FilterValue = string | readonly string[] | readonly [number | null, number | null];\n/** The filters in force, by column id. */\nexport type DataTableFilterState = Readonly<Record<string, FilterValue>>;\n\nconst empty = (value: CellValue) => value == null || value === \"\";\n\n/** The order of two values: empty last, dates and numbers by value, text in natural order (\"item 2\" < \"item 10\"). */\nexport function compareValues(a: CellValue, b: CellValue): number {\n if (empty(a)) return empty(b) ? 0 : 1;\n if (empty(b)) return -1;\n if (a instanceof Date || b instanceof Date) return Number(a) - Number(b);\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return String(a).localeCompare(String(b), undefined, { numeric: true, sensitivity: \"base\" });\n}\n\nexport const sortByValue: SortFn<Features, never> = (a, b, id) => compareValues(a.getValue(id) as CellValue, b.getValue(id) as CellValue);\n\n/** A text filter: the value contains the words, case and accents ignored. */\nexport const filterText: FilterFn<Features, never> = (row, id, query: string) =>\n String(row.getValue(id) ?? \"\")\n .normalize(\"NFD\")\n .toLocaleLowerCase()\n .includes(query.normalize(\"NFD\").toLocaleLowerCase().trim());\nfilterText.autoRemove = (value: unknown) => typeof value !== \"string\" || value.trim() === \"\";\n\n/** A facet filter: the value is one of those chosen. */\nexport const filterFacet: FilterFn<Features, never> = (row, id, chosen: readonly string[]) => chosen.includes(String(row.getValue(id) ?? \"\"));\nfilterFacet.autoRemove = (value: unknown) => !Array.isArray(value) || value.length === 0;\n\n/** A range filter: the value (a number or a date) lies within the bounds, either of which may be open. */\nexport const filterRange: FilterFn<Features, never> = (row, id, [min, max]: readonly [number | null, number | null]) => {\n const raw = row.getValue(id) as CellValue;\n if (empty(raw)) return false;\n const value = Number(raw);\n return (min == null || value >= min) && (max == null || value <= max);\n};\nfilterRange.autoRemove = (value: unknown) => !Array.isArray(value) || (value[0] == null && value[1] == null);\n\nexport const FILTERS = { text: filterText, facet: filterFacet, range: filterRange } as const;\n\nexport type { ColumnDef, ColumnResizingState, RowData };\n","\"use client\";\nimport * as React from \"react\";\n\nimport { useRouteSearch } from \"../router\";\nimport type { DataTableFilterState } from \"./engine\";\nimport { decodeSort, encodeSort, readTable, type RouteDefaults, type RouteSort, writeTable } from \"./route-codec\";\n\n/** `DataTable`'s `routeKey`: the sort, the filters and the page read from the address, and written to it. Inert without a key. */\nexport function useRouteTable(routeKey: string | undefined, defaults: Required<RouteDefaults>, columns: readonly string[]) {\n const { search, write } = useRouteSearch();\n const key = routeKey;\n // The defaults by value: a table's `defaultFilters={{…}}` is a new object at each render.\n const sortKey = encodeSort(defaults.sort);\n const filtersKey = JSON.stringify(defaults.filters);\n const columnKey = columns.join();\n const page = defaults.page;\n const stable = React.useMemo<Required<RouteDefaults>>(\n () => ({ sort: decodeSort(sortKey, null), page, filters: JSON.parse(filtersKey) as DataTableFilterState }),\n [sortKey, filtersKey, page],\n );\n // Stable between renders while the address is the same: the table's filters are compared by identity.\n const table = React.useMemo(\n () => (key === undefined ? null : readTable(search, key, stable, columnKey.split(\",\"))),\n [search, key, stable, columnKey],\n );\n if (key === undefined || table === null) return null;\n return {\n sort: table.sort,\n filters: table.filters,\n page: table.page,\n // Typing in a filter is not a place to come back to: it replaces the entry; a sort or a page is a step. A sort or a\n // filter goes back to the first page in the same navigation.\n onSortChange: (sort: RouteSort) => write((s) => writeTable(s, key, { sort }, stable)),\n onFiltersChange: (filters: DataTableFilterState) => write((s) => writeTable(s, key, { filters }, stable), { replace: true }),\n onPageChange: (next: number) => write((s) => writeTable(s, key, { page: next }, stable)),\n };\n}\n","// The table's sort, filters and page as search parameters: pure, so the address and the tests share them. With\n// `routeKey=\"clients\"` the address reads `?clients.sort=visits.descending&clients.q.client=lea&clients.page=2`; a value equal to\n// the table's own default is not written (a clean URL).\nimport type { DataTableFilterState, FilterValue } from \"./engine\";\n\nexport type RouteSort = { column: string; direction: \"ascending\" | \"descending\" } | null;\n\nconst NONE = \"none\";\n\nexport function encodeSort(sort: RouteSort): string {\n return sort ? `${sort.column}.${sort.direction}` : NONE;\n}\n\nexport function decodeSort(raw: string | null, fallback: RouteSort, columns?: readonly string[]): RouteSort {\n if (raw === null) return fallback;\n if (raw === NONE) return null;\n const dot = raw.lastIndexOf(\".\");\n const column = raw.slice(0, dot);\n const direction = raw.slice(dot + 1);\n if (dot < 1 || (direction !== \"ascending\" && direction !== \"descending\") || (columns && !columns.includes(column))) return fallback;\n return { column, direction };\n}\n\n// A text is written as typed, an array as JSON. A text that would read as JSON (it starts with `[`) or as an escaped one\n// (`\\`) is escaped with a leading backslash, so `\"[1,2]\"` typed in a text filter comes back as text, never as an array.\nconst ESCAPE = \"\\\\\";\n\nexport function encodeFilter(value: FilterValue): string {\n if (typeof value !== \"string\") return JSON.stringify(value);\n return value.startsWith(\"[\") || value.startsWith(ESCAPE) ? `${ESCAPE}${value}` : value;\n}\n\nexport function decodeFilter(raw: string): FilterValue {\n if (raw.startsWith(ESCAPE)) return raw.slice(1);\n if (raw.startsWith(\"[\")) {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed as FilterValue;\n } catch {\n // a text that merely starts with a bracket\n }\n }\n return raw;\n}\n\nconst sameSort = (a: RouteSort, b: RouteSort) => a?.column === b?.column && a?.direction === b?.direction;\nconst filterPrefix = (key: string) => `${key}.q.`;\n// Present (empty) when the filters were cleared while the table's defaults have some: « none » is not « the defaults ».\nconst clearedFilters = (key: string) => `${key}.q`;\n\n/** The table's own starting state: what an address without its parameters means. */\nexport type RouteDefaults = { sort: RouteSort; page: number; filters?: DataTableFilterState };\n\nconst sameFilters = (a: DataTableFilterState, b: DataTableFilterState) => {\n const written = (f: DataTableFilterState) =>\n JSON.stringify(Object.entries(f).map(([column, value]) => [column, encodeFilter(value)]).filter(([, v]) => v !== \"\" && v !== \"[]\").sort(([a], [b]) => String(a).localeCompare(String(b))));\n return written(a) === written(b);\n};\n\nexport function readTable(search: string, key: string, defaults: RouteDefaults, columns?: readonly string[]) {\n const params = new URLSearchParams(search);\n const filters: Record<string, FilterValue> = {};\n let explicit = params.has(clearedFilters(key));\n for (const [name, raw] of params) {\n if (!name.startsWith(filterPrefix(key)) || raw === \"\") continue;\n explicit = true;\n filters[name.slice(filterPrefix(key).length)] = decodeFilter(raw);\n }\n const raw = params.get(`${key}.page`);\n const page = raw !== null && /^[1-9]\\d*$/.test(raw) ? Number(raw) : defaults.page;\n return {\n sort: decodeSort(params.get(`${key}.sort`), defaults.sort, columns),\n filters: (explicit ? filters : (defaults.filters ?? {})) as DataTableFilterState,\n page,\n };\n}\n\ntype Change = { sort?: RouteSort; filters?: DataTableFilterState; page?: number };\n\n/**\n * The query string with the table's parameters changed; every other parameter is kept. A change of sort or filters goes\n * back to the first page (as the table does) unless it says otherwise; a value equal to the default is not written.\n */\nexport function writeTable(search: string, key: string, change: Change, defaults: RouteDefaults): string {\n const params = new URLSearchParams(search);\n if (change.sort !== undefined) {\n if (sameSort(change.sort, defaults.sort)) params.delete(`${key}.sort`);\n else params.set(`${key}.sort`, encodeSort(change.sort));\n }\n if (change.filters !== undefined) {\n for (const name of [...params.keys()]) if (name.startsWith(filterPrefix(key)) || name === clearedFilters(key)) params.delete(name);\n if (!sameFilters(change.filters, defaults.filters ?? {})) {\n let written = 0;\n for (const [column, value] of Object.entries(change.filters)) {\n const encoded = encodeFilter(value);\n if (encoded !== \"\" && encoded !== \"[]\") {\n params.set(`${filterPrefix(key)}${column}`, encoded);\n written += 1;\n }\n }\n if (written === 0) params.set(clearedFilters(key), \"\");\n }\n }\n const page = change.page ?? (change.sort !== undefined || change.filters !== undefined ? 1 : undefined);\n if (page !== undefined) {\n if (page === defaults.page) params.delete(`${key}.page`);\n else params.set(`${key}.page`, String(page));\n }\n const text = params.toString();\n return text ? `?${text}` : \"\";\n}\n","// The toolbar of a DataTable — its filters (a FilterBar built from the columns), the columns menu and the CSV export —\n// connected to the table they sit in through `useDataTable()`. Words come from the table's `labels`.\nimport * as React from \"react\";\n\nimport { Button } from \"../button\";\nimport { DropdownMenu } from \"../dropdown-menu\";\nimport { Input } from \"../field\";\nimport { type ActiveFilter, FilterBar, FilterMenu } from \"../filter-bar\";\nimport { ChevronGlyph } from \"../glyphs\";\nimport { SearchField } from \"../search-field\";\nimport { dataTableCsv } from \"./csv\";\nimport { type DataTableColumn, useDataTable } from \"./data-table\";\nimport type { FilterValue } from \"./engine\";\n\nexport type DataTableFiltersProps = {\n /** The search's wait after the last key, in ms, before the filter applies (a request, in server mode). Default 250. */\n debounce?: number;\n /** More controls in the bar (a date range picker, a toggle). */\n children?: React.ReactNode;\n /** Classes merged on the bar. */\n className?: string;\n};\n\nconst asRange = (value: FilterValue | undefined): [number | null, number | null] =>\n Array.isArray(value) && value.length === 2 && (typeof value[0] !== \"string\" || typeof value[1] !== \"string\") ? [value[0] as number | null, value[1] as number | null] : [null, null];\nconst asList = (value: FilterValue | undefined): readonly string[] => (Array.isArray(value) ? (value as readonly string[]) : []);\nconst number = (text: string) => (text.trim() === \"\" || Number.isNaN(Number(text)) ? null : Number(text));\n\n/**\n * The filters of the table, from its columns: a search per `text` column, a menu of values (with their counts) per\n * `facet` column, two bounds per `range` column; the filters in force as removable chips, \"clear all\", and the count\n * of results, announced.\n */\nexport function DataTableFilters({ debounce = 250, children, className }: DataTableFiltersProps) {\n const { table, columns, labels, filters, setFilters, resultCount, manualFiltering } = useDataTable();\n const set = (id: string, value: FilterValue | null) => {\n const next = { ...filters };\n if (value === null || value === \"\" || (Array.isArray(value) && (value.length === 0 || (value.length === 2 && value[0] == null && value[1] == null)))) delete next[id];\n else next[id] = value;\n setFilters(next);\n };\n const filterable = columns.filter((column) => column.filter);\n const optionsOf = (column: DataTableColumn<object>) => {\n if (column.options) return column.options;\n // The values found in the rows, with their counts — the other filters applied (TanStack's facets).\n const facets = manualFiltering ? new Map<unknown, number>() : (table.getColumn(column.id)?.getFacetedUniqueValues() ?? new Map<unknown, number>());\n return [...facets.entries()]\n .filter(([value]) => value != null && value !== \"\")\n .map(([value, count]) => ({ value: String(value), label: String(value), count }))\n .sort((a, b) => a.label.localeCompare(b.label, undefined, { numeric: true }));\n };\n const active: ActiveFilter[] = filterable.flatMap((column) => {\n const value = filters[column.id];\n if (value === undefined) return [];\n let text: string;\n if (column.filter === \"facet\") {\n const options = optionsOf(column);\n text = asList(value).map((v) => options.find((o) => o.value === v)?.label ?? v).join(\", \");\n } else if (column.filter === \"range\") {\n const [min, max] = asRange(value);\n text = `${min ?? \"…\"}–${max ?? \"…\"}`;\n } else text = String(value);\n const label = labels.activeFilter(column.header, text);\n return [{ id: column.id, label, onRemove: () => set(column.id, null) }];\n });\n return (\n <FilterBar\n label={labels.filters}\n active={active}\n onClearAll={() => setFilters({})}\n clearLabel={labels.clearFilters}\n removeLabel={labels.removeFilter}\n results={labels.results(resultCount)}\n className={className}\n >\n {filterable.map((column) => {\n if (column.filter === \"text\")\n return (\n <TextFilter\n key={column.id}\n label={labels.search(column.header)}\n value={typeof filters[column.id] === \"string\" ? (filters[column.id] as string) : \"\"}\n debounce={debounce}\n onCommit={(query) => set(column.id, query)}\n />\n );\n if (column.filter === \"facet\")\n return (\n <FilterMenu key={column.id} label={column.header} options={optionsOf(column)} value={asList(filters[column.id])} onValueChange={(value) => set(column.id, value)} />\n );\n const [min, max] = asRange(filters[column.id]);\n const bounds = manualFiltering ? undefined : table.getColumn(column.id)?.getFacetedMinMaxValues();\n return (\n <span key={column.id} className=\"inline-flex items-center gap-1.5\">\n <Input\n type=\"number\"\n inputMode=\"decimal\"\n aria-label={labels.rangeFrom(column.header)}\n placeholder={bounds ? String(bounds[0]) : labels.rangeFrom(column.header)}\n value={min ?? \"\"}\n onChange={(event) => set(column.id, [number(event.currentTarget.value), max])}\n className=\"h-11 w-28\"\n />\n <span aria-hidden className=\"text-fg-secondary\">\n –\n </span>\n <Input\n type=\"number\"\n inputMode=\"decimal\"\n aria-label={labels.rangeTo(column.header)}\n placeholder={bounds ? String(bounds[1]) : labels.rangeTo(column.header)}\n value={max ?? \"\"}\n onChange={(event) => set(column.id, [min, number(event.currentTarget.value)])}\n className=\"h-11 w-28\"\n />\n </span>\n );\n })}\n {children}\n </FilterBar>\n );\n}\n\nexport type DataTableColumnsMenuProps = {\n /** Opens the menu at first (a story, a test). */\n defaultOpen?: boolean;\n /** Classes merged on the button. */\n className?: string;\n};\n\n/** A menu of the `hideable` columns, each a checkbox: the person chooses what the table shows. */\nexport function DataTableColumnsMenu({ defaultOpen, className }: DataTableColumnsMenuProps) {\n const { table, columns, labels } = useDataTable();\n return (\n <DropdownMenu.Root defaultOpen={defaultOpen} modal={false}>\n <DropdownMenu.Trigger asChild>\n <Button variant=\"outline\" size=\"sm\" className={className}>\n {labels.columns}\n <ChevronGlyph className=\"h-4 w-4\" />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" aria-label={labels.columns}>\n {columns\n .filter((column) => column.hideable !== false)\n .map((column) => {\n const instance = table.getColumn(column.id);\n return (\n <DropdownMenu.CheckboxItem\n key={column.id}\n checked={instance?.getIsVisible() ?? true}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(checked) => instance?.toggleVisibility(Boolean(checked))}\n >\n {column.header}\n </DropdownMenu.CheckboxItem>\n );\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\nexport type DataTableExportProps = {\n /** The file's name. Default `\"export.csv\"`. */\n filename?: string;\n /** Receives the CSV instead of downloading it (send it to the server, a test). */\n onExport?: (csv: string) => void;\n /** Classes merged on the button. */\n className?: string;\n};\n\n/** Downloads what the table shows — the filtered and sorted rows of every page, the visible columns — as CSV. */\nexport function DataTableExport({ filename = \"export.csv\", onExport, className }: DataTableExportProps) {\n const { table, columns, labels, exportRows } = useDataTable();\n const run = () => {\n const visible = columns.filter((column) => table.getColumn(column.id)?.getIsVisible() !== false);\n const csv = dataTableCsv(exportRows(), visible);\n if (onExport) return onExport(csv);\n const url = URL.createObjectURL(new Blob([\"\", csv], { type: \"text/csv;charset=utf-8\" }));\n const link = Object.assign(document.createElement(\"a\"), { href: url, download: filename });\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n };\n return (\n <Button variant=\"outline\" size=\"sm\" className={className} onClick={run}>\n {labels.export}\n </Button>\n );\n}\n\n/**\n * A text filter: what is typed stays a draft until the debounce commits it, and a value that changes from outside\n * (back or forward on a `routeKey` table, « Clear all ») replaces the draft — the box always says what filters the rows.\n */\nfunction TextFilter({ label, value, debounce, onCommit }: { label: string; value: string; debounce?: number; onCommit: (query: string) => void }) {\n const [draft, setDraft] = React.useState(value);\n const [seen, setSeen] = React.useState(value);\n const [committed, setCommitted] = React.useState(value);\n if (value !== seen) {\n setSeen(value);\n if (value !== committed) {\n setCommitted(value);\n setDraft(value);\n }\n }\n return (\n <SearchField\n label={label}\n placeholder={label}\n value={draft}\n onValueChange={setDraft}\n debounce={debounce}\n onSearch={(query) => {\n setCommitted(query);\n onCommit(query);\n }}\n landmark={false}\n size=\"sm\"\n className=\"min-w-48 flex-1\"\n />\n );\n}\n","// Server-safe. The label ↔ control wiring is HTML (htmlFor / id, aria-describedby): no context.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\n\nexport const field = tv({\n slots: {\n root: \"flex flex-col gap-1.5\",\n label: \"text-xs font-semibold text-fg-secondary\",\n control:\n \"flex h-11 w-full rounded-lg border border-border-control bg-surface-2 px-3 text-sm text-fg placeholder:text-fg-muted \" +\n \"transition-[border-color,box-shadow] focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n \"disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger aria-invalid:ring-danger/30\",\n hint: \"text-xs text-fg-secondary\",\n // The message reads in the danger text role (≥ 4.5:1 on every surface, both themes); the dot is the danger fill.\n error: \"flex items-center gap-1.5 text-xs font-medium text-fg-danger before:h-1.5 before:w-1.5 before:shrink-0 before:rounded-full before:bg-danger\",\n selectWrap: \"relative flex w-full\",\n chevron: \"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-secondary\",\n },\n});\nconst s = field();\n\nexport const Field = {\n Root: ({ className, ...props }: React.ComponentProps<\"div\">) => <div className={s.root({ className })} {...props} />,\n Label: ({ className, ...props }: React.ComponentProps<\"label\">) => <label className={s.label({ className })} {...props} />,\n Hint: ({ className, ...props }: React.ComponentProps<\"p\">) => <p className={s.hint({ className })} {...props} />,\n Error: ({ className, ...props }: React.ComponentProps<\"p\">) => <p role=\"alert\" className={s.error({ className })} {...props} />,\n};\n\ntype ControlProps = {\n /** Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n};\n\nconst invalidProps = (invalid?: boolean) => (invalid ? { \"aria-invalid\": true as const, \"data-invalid\": \"\" } : {});\n\nexport function Input({ invalid, className, ...props }: React.ComponentProps<\"input\"> & ControlProps) {\n return <input {...invalidProps(invalid)} className={s.control({ className })} {...props} />;\n}\n\nexport function Textarea({ invalid, className, ...props }: React.ComponentProps<\"textarea\"> & ControlProps) {\n return <textarea {...invalidProps(invalid)} className={s.control({ className: cn(\"h-auto min-h-24 py-2\", className) })} {...props} />;\n}\n\n/** A native <select>, styled like the other controls (the platform's menu: accessible and right on phones). */\nexport function Select({ invalid, className, ...props }: React.ComponentProps<\"select\"> & ControlProps) {\n return (\n <span className={s.selectWrap()}>\n <select {...invalidProps(invalid)} className={s.control({ className: cn(\"appearance-none pr-9\", className) })} {...props} />\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className={s.chevron()}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </span>\n );\n}\n"],"mappings":"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","names":["React","tv","s","a","b","raw","s","jsx","jsxs","tv","NONE","empty","s","pagination","React","tv","jsx","jsxs","field","tv","jsx","jsx","jsxs"]}
@@ -26,7 +26,7 @@ var sites = [
26
26
  site({ id: "akinaza", name: "Akinaza", url: "https://www.akinaza.com", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
27
27
  site({ id: "ui", name: "Krizaka UI", url: "https://ui.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ui" }),
28
28
  site({ id: "java", name: "Krizaka Java", url: "https://java.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-build" }),
29
- site({ id: "ts", name: "Krizaka TS", url: "https://ts.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ts" }),
29
+ site({ id: "ts", name: "Krizaka TypeScript", url: "https://ts.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ts" }),
30
30
  // The motion lab: built in the open on GitHub Pages; what proves itself there moves into Krizaka UI.
31
31
  site({ id: "motion", name: "Krizaka Motion", url: "https://krizaka.github.io/krizaka-motion", kind: "open-source", group: "open-source", status: "development", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-motion" }),
32
32
  site({ id: "github", name: "GitHub", url: "https://github.com/krizaka", kind: "open-source", group: "github", status: "released", mark: "github", repo: "https://github.com/krizaka" })
@@ -108,4 +108,4 @@ export {
108
108
  companyLinks,
109
109
  familyLabels
110
110
  };
111
- //# sourceMappingURL=chunk-4LYKBSOG.js.map
111
+ //# sourceMappingURL=chunk-USPOIQV5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/family-mark.tsx","../src/sites/sites.ts"],"sourcesContent":["// The mark of a site of the family (`@krizaka/ui/sites`): its brand's `ProductLogo`, still (a list of marks never\n// moves), or GitHub's, in the text colour. Shared by `NavBar.Family` and `SiteFooter` — not an entry of its own.\nimport type * as React from \"react\";\n\nimport { ProductLogo } from \"./marks/ProductLogo\";\nimport type { SiteMark } from \"./sites/sites\";\n\n/** GitHub's mark, in the text colour (both themes). */\nexport function GitHubGlyph({ size = 16, className }: { size?: number; className?: string }) {\n return (\n <svg viewBox=\"0 0 16 16\" width={size} height={size} fill=\"currentColor\" aria-hidden className={className}>\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z\" />\n </svg>\n );\n}\n\n/** A site's mark, decorative (its name is always written beside it). */\nexport function FamilyMark({ mark, size }: { mark: SiteMark; size: number }): React.ReactElement {\n if (mark === \"github\") return <GitHubGlyph size={Math.round(size * 0.8)} />;\n return <ProductLogo id={mark} size={size} animated={false} />;\n}\n","// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"ts\" | \"motion\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing offered (a QA-only app may run; the public page says so). `development`: being built in the\n * open, with a dev site (said \"In development\"). A site with none yet would use its repository as its address.\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://www.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://www.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://www.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://www.yororis.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://www.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://www.kachizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://www.akinaza.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n site({ id: \"ts\", name: \"Krizaka TypeScript\", url: \"https://ts.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ts\" }),\n // The motion lab: built in the open on GitHub Pages; what proves itself there moves into Krizaka UI.\n site({ id: \"motion\", name: \"Krizaka Motion\", url: \"https://krizaka.github.io/krizaka-motion\", kind: \"open-source\", group: \"open-source\", status: \"development\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-motion\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The company's own pages, the footer's « Krizaka » column (the brand's home is the signature line's link). */\nexport type CompanyLinkId = \"story\" | \"blog\" | \"contact\";\nexport const companyLinks: readonly { id: CompanyLinkId; url: Record<SiteLocale, string> }[] = [\n { id: \"story\", url: { en: \"https://www.krizaka.com/story\", fr: \"https://www.krizaka.com/fr/story\" } },\n { id: \"blog\", url: { en: \"https://blog.krizaka.com\", fr: \"https://blog.krizaka.com\" } },\n { id: \"contact\", url: { en: \"https://www.krizaka.com/contact\", fr: \"https://www.krizaka.com/fr/contact\" } },\n];\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n /** The language of these words: the company links open in it. @default \"en\" */\n lang?: SiteLocale;\n /** The company's pages in the footer's « Krizaka » column. @default the English words */\n company?: Record<CompanyLinkId, string>;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI on your own servers: chat, documents, images and video — and the engine under the other products.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"Meet real people: introductions, and photos checked before you see them.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n ts: \"TypeScript backend building blocks on npm.\",\n motion: \"The motion lab: the kit's motion, played live with its knobs.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n lang: \"en\",\n company: { story: \"Our story\", blog: \"Blog\", contact: \"Contact us\" },\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine sur vos propres serveurs : conversation, documents, images et vidéo — et le moteur des autres produits.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"Rencontrez de vraies personnes : des présentations, et des photos vérifiées avant que vous les voyiez.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n ts: \"Des briques backend TypeScript sur npm.\",\n motion: \"Le labo du mouvement : le mouvement du kit, joué en direct, avec ses réglages.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n lang: \"fr\",\n company: { story: \"Notre histoire\", blog: \"Blogue\", contact: \"Nous écrire\" },\n },\n};\n"],"mappings":"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","names":[]}
@@ -32,7 +32,7 @@ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
32
32
  var searchField = tv2({
33
33
  slots: {
34
34
  root: "relative w-full",
35
- control: "flex h-11 w-full items-center gap-2 rounded-lg border border-border-default bg-surface-2 pl-3 pr-1.5 text-sm text-fg transition-[border-color,box-shadow] focus-within:border-accent focus-within:ring-2 focus-within:ring-ring",
35
+ control: "flex h-11 w-full items-center gap-2 rounded-lg border border-border-control bg-surface-2 pl-3 pr-1.5 text-sm text-fg transition-[border-color,box-shadow] focus-within:border-accent focus-within:ring-2 focus-within:ring-ring",
36
36
  icon: "h-4 w-4 shrink-0 text-fg-secondary",
37
37
  input: "h-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted [&::-webkit-search-cancel-button]:appearance-none",
38
38
  clear: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-fg-secondary hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
@@ -165,4 +165,4 @@ export {
165
165
  searchField,
166
166
  SearchField
167
167
  };
168
- //# sourceMappingURL=chunk-7NRSPHAF.js.map
168
+ //# sourceMappingURL=chunk-VB7MWE2N.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/search-field/search-field.tsx","../src/kbd/kbd.tsx"],"sourcesContent":["// Client. A search input (`type=\"search\"` inside a `role=\"search\"` landmark when it stands alone): a leading glyph,\n// a clear button, a global shortcut that focuses it (⌘K on Apple devices, Ctrl+K elsewhere, shown as `Kbd`), and\n// optional suggestions through the shared combobox engine. `onSearch` is debounced; Enter submits.\nimport { useDebouncedCallback } from \"@krizaka/pacer/react\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CloseGlyph, SearchGlyph } from \"../glyphs\";\nimport { Kbd } from \"../kbd\";\nimport { useListbox } from \"../listbox\";\nimport { useControllable } from \"../media\";\n\nexport const searchField = tv({\n slots: {\n root: \"relative w-full\",\n control:\n \"flex h-11 w-full items-center gap-2 rounded-lg border border-border-default bg-surface-2 pl-3 pr-1.5 text-sm text-fg \" +\n \"transition-[border-color,box-shadow] focus-within:border-accent focus-within:ring-2 focus-within:ring-ring\",\n icon: \"h-4 w-4 shrink-0 text-fg-secondary\",\n input:\n \"h-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted \" +\n \"[&::-webkit-search-cancel-button]:appearance-none\",\n clear:\n \"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-fg-secondary hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n shortcut: \"hidden shrink-0 items-center gap-0.5 pr-1 sm:flex\",\n list: \"absolute inset-x-0 top-full z-50 mt-1 max-h-72 overflow-y-auto rounded-lg border border-border-default bg-surface-2 p-1 shadow-lg\",\n option: \"flex cursor-pointer select-none items-center gap-2.5 rounded-md px-2.5 py-2 text-sm text-fg data-[active]:bg-surface-3\",\n group: \"px-2.5 pb-1 pt-2 text-[11px] font-semibold text-fg-muted\",\n },\n variants: {\n size: { md: {}, sm: { control: \"h-9\", clear: \"h-7 w-7\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type SearchSuggestion = {\n /** What `onSuggestionSelect` receives. */\n value: string;\n /** What the person reads. */\n label: string;\n /** A small text on the right (\"Creator\", \"12 videos\"). */\n meta?: string;\n};\n\nexport type SearchFieldProps = Omit<React.ComponentProps<\"input\">, \"value\" | \"defaultValue\" | \"onChange\" | \"onSubmit\" | \"size\" | \"type\"> & {\n /** The accessible name of the input (\"Search videos\"), passed translated. */\n label: string;\n /** The query (controlled). */\n value?: string;\n /** The query at first, uncontrolled. */\n defaultValue?: string;\n /** Called on every key with the query. */\n onValueChange?: (query: string) => void;\n /** Called with the query once typing pauses (`debounce` ms): fetch the results here. */\n onSearch?: (query: string) => void;\n /** The pause, in ms, before `onSearch`. Default 250. */\n debounce?: number;\n /** Called on Enter (no suggestion active) with the query: go to the results page. */\n onSubmit?: (query: string) => void;\n /** The global key that focuses the field with ⌘ / Ctrl (`\"k\"`), or `false` for none. Default `false`. */\n shortcut?: string | false;\n /** Suggestions under the field (recent searches, completions). */\n suggestions?: readonly SearchSuggestion[];\n /** A title above the suggestions (\"Recent searches\"). */\n suggestionsLabel?: string;\n /** Called with a suggestion picked (Enter on it, or a click). */\n onSuggestionSelect?: (suggestion: SearchSuggestion) => void;\n /** The clear button's name (\"Clear search\"), passed translated. */\n clearLabel?: string;\n /** Wraps the field in a `role=\"search\"` landmark (default) — `false` inside a form that already is one. */\n landmark?: boolean;\n /** md (default) · sm. */\n size?: \"md\" | \"sm\";\n};\n\nconst isApple = () => typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n\n/** A search box: clear, shortcut, debounced search, submit on Enter, suggestions with the keyboard. */\nexport function SearchField({\n label,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n onSearch,\n debounce = 250,\n onSubmit,\n shortcut = false,\n suggestions,\n suggestionsLabel,\n onSuggestionSelect,\n clearLabel = \"Clear search\",\n landmark = true,\n size,\n className,\n placeholder,\n ...props\n}: SearchFieldProps) {\n const s = searchField({ size });\n const [value, setValue] = useControllable(valueProp, defaultValue, onValueChange);\n const [open, setOpen] = React.useState(false);\n const [apple, setApple] = React.useState(false);\n const input = React.useRef<HTMLInputElement>(null);\n const search = useDebouncedCallback((query: string) => onSearch?.(query), debounce);\n const list = suggestions ?? [];\n\n const pick = (i: number) => {\n const suggestion = list[i];\n if (!suggestion) return;\n setOpen(false);\n onSuggestionSelect?.(suggestion);\n };\n const listbox = useListbox({ count: list.length, onPick: pick, open: open && list.length > 0, setOpen });\n\n React.useEffect(() => {\n if (!shortcut) return;\n // eslint-disable-next-line react-hooks/set-state-in-effect -- the platform is only known in the browser (no hydration mismatch)\n setApple(isApple());\n const onKey = (event: KeyboardEvent) => {\n if (event.key.toLowerCase() === shortcut.toLowerCase() && (event.metaKey || event.ctrlKey) && !event.altKey) {\n event.preventDefault();\n input.current?.focus();\n input.current?.select();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [shortcut]);\n\n const change = (query: string) => {\n setValue(query);\n search(query);\n listbox.setActive(-1);\n setOpen(true);\n };\n\n const field = (\n <div className={s.root({ className })} onBlur={(event) => !event.currentTarget.contains(event.relatedTarget as Node | null) && setOpen(false)}>\n <div className={s.control()}>\n <SearchGlyph className={s.icon()} />\n <input\n ref={input}\n type=\"search\"\n aria-label={label}\n enterKeyHint=\"search\"\n autoComplete=\"off\"\n {...(list.length > 0 ? listbox.inputProps : {})}\n value={value}\n placeholder={placeholder}\n className={s.input()}\n onChange={(event) => change(event.target.value)}\n onFocus={() => setOpen(true)}\n onKeyDown={(event) => {\n if (list.length > 0 && listbox.onKeyDown(event)) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n search.cancel();\n onSearch?.(value);\n onSubmit?.(value);\n setOpen(false);\n } else if (event.key === \"Escape\" && value) {\n event.preventDefault();\n change(\"\");\n }\n }}\n {...props}\n />\n {value ? (\n <button\n type=\"button\"\n aria-label={clearLabel}\n className={s.clear()}\n onClick={() => {\n change(\"\");\n input.current?.focus();\n }}\n >\n <CloseGlyph className=\"h-4 w-4\" />\n </button>\n ) : shortcut ? (\n <span className={s.shortcut()} aria-hidden>\n <Kbd size=\"sm\">{apple ? \"⌘\" : \"Ctrl\"}</Kbd>\n <Kbd size=\"sm\">{shortcut.toUpperCase()}</Kbd>\n </span>\n ) : null}\n </div>\n {list.length > 0 && (\n <div hidden={!open} className={s.list()}>\n {suggestionsLabel ? (\n <div aria-hidden className={s.group()}>\n {suggestionsLabel}\n </div>\n ) : null}\n <div id={listbox.listId} role=\"listbox\" aria-label={suggestionsLabel ?? label}>\n {list.map((suggestion, i) => (\n <div key={suggestion.value} {...listbox.optionProps(i, false)} className={s.option()}>\n <SearchGlyph className=\"h-3.5 w-3.5 shrink-0 text-fg-muted\" />\n <span className=\"min-w-0 flex-1 truncate\">{suggestion.label}</span>\n {suggestion.meta ? <span className=\"shrink-0 text-xs text-fg-secondary\">{suggestion.meta}</span> : null}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n return landmark ? <div role=\"search\">{field}</div> : field;\n}\n","// Server-safe. A key, or a shortcut of several (`<Kbd>⌘</Kbd><Kbd>K</Kbd>`).\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const kbdVariants = tv({\n base:\n \"inline-flex shrink-0 items-center justify-center rounded-md border border-border-default border-b-2 bg-surface-2 \" +\n \"font-mono font-semibold text-fg-secondary\",\n variants: { size: { sm: \"h-5 min-w-5 px-1 text-[10px]\", md: \"h-6 min-w-6 px-1.5 text-xs\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type KbdProps = React.ComponentProps<\"kbd\"> & {\n /**\n * sm · md.\n * @default \"md\"\n */\n size?: VariantProps<typeof kbdVariants>[\"size\"];\n};\n\nexport function Kbd({ size, className, ...props }: KbdProps) {\n return <kbd className={kbdVariants({ size, className })} {...props} />;\n}\n"],"mappings":"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","names":["tv","jsx","tv"]}
1
+ {"version":3,"sources":["../src/search-field/search-field.tsx","../src/kbd/kbd.tsx"],"sourcesContent":["// Client. A search input (`type=\"search\"` inside a `role=\"search\"` landmark when it stands alone): a leading glyph,\n// a clear button, a global shortcut that focuses it (⌘K on Apple devices, Ctrl+K elsewhere, shown as `Kbd`), and\n// optional suggestions through the shared combobox engine. `onSearch` is debounced; Enter submits.\nimport { useDebouncedCallback } from \"@krizaka/pacer/react\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CloseGlyph, SearchGlyph } from \"../glyphs\";\nimport { Kbd } from \"../kbd\";\nimport { useListbox } from \"../listbox\";\nimport { useControllable } from \"../media\";\n\nexport const searchField = tv({\n slots: {\n root: \"relative w-full\",\n control:\n \"flex h-11 w-full items-center gap-2 rounded-lg border border-border-control bg-surface-2 pl-3 pr-1.5 text-sm text-fg \" +\n \"transition-[border-color,box-shadow] focus-within:border-accent focus-within:ring-2 focus-within:ring-ring\",\n icon: \"h-4 w-4 shrink-0 text-fg-secondary\",\n input:\n \"h-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted \" +\n \"[&::-webkit-search-cancel-button]:appearance-none\",\n clear:\n \"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-fg-secondary hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n shortcut: \"hidden shrink-0 items-center gap-0.5 pr-1 sm:flex\",\n list: \"absolute inset-x-0 top-full z-50 mt-1 max-h-72 overflow-y-auto rounded-lg border border-border-default bg-surface-2 p-1 shadow-lg\",\n option: \"flex cursor-pointer select-none items-center gap-2.5 rounded-md px-2.5 py-2 text-sm text-fg data-[active]:bg-surface-3\",\n group: \"px-2.5 pb-1 pt-2 text-[11px] font-semibold text-fg-muted\",\n },\n variants: {\n size: { md: {}, sm: { control: \"h-9\", clear: \"h-7 w-7\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type SearchSuggestion = {\n /** What `onSuggestionSelect` receives. */\n value: string;\n /** What the person reads. */\n label: string;\n /** A small text on the right (\"Creator\", \"12 videos\"). */\n meta?: string;\n};\n\nexport type SearchFieldProps = Omit<React.ComponentProps<\"input\">, \"value\" | \"defaultValue\" | \"onChange\" | \"onSubmit\" | \"size\" | \"type\"> & {\n /** The accessible name of the input (\"Search videos\"), passed translated. */\n label: string;\n /** The query (controlled). */\n value?: string;\n /** The query at first, uncontrolled. */\n defaultValue?: string;\n /** Called on every key with the query. */\n onValueChange?: (query: string) => void;\n /** Called with the query once typing pauses (`debounce` ms): fetch the results here. */\n onSearch?: (query: string) => void;\n /** The pause, in ms, before `onSearch`. Default 250. */\n debounce?: number;\n /** Called on Enter (no suggestion active) with the query: go to the results page. */\n onSubmit?: (query: string) => void;\n /** The global key that focuses the field with ⌘ / Ctrl (`\"k\"`), or `false` for none. Default `false`. */\n shortcut?: string | false;\n /** Suggestions under the field (recent searches, completions). */\n suggestions?: readonly SearchSuggestion[];\n /** A title above the suggestions (\"Recent searches\"). */\n suggestionsLabel?: string;\n /** Called with a suggestion picked (Enter on it, or a click). */\n onSuggestionSelect?: (suggestion: SearchSuggestion) => void;\n /** The clear button's name (\"Clear search\"), passed translated. */\n clearLabel?: string;\n /** Wraps the field in a `role=\"search\"` landmark (default) — `false` inside a form that already is one. */\n landmark?: boolean;\n /** md (default) · sm. */\n size?: \"md\" | \"sm\";\n};\n\nconst isApple = () => typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n\n/** A search box: clear, shortcut, debounced search, submit on Enter, suggestions with the keyboard. */\nexport function SearchField({\n label,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n onSearch,\n debounce = 250,\n onSubmit,\n shortcut = false,\n suggestions,\n suggestionsLabel,\n onSuggestionSelect,\n clearLabel = \"Clear search\",\n landmark = true,\n size,\n className,\n placeholder,\n ...props\n}: SearchFieldProps) {\n const s = searchField({ size });\n const [value, setValue] = useControllable(valueProp, defaultValue, onValueChange);\n const [open, setOpen] = React.useState(false);\n const [apple, setApple] = React.useState(false);\n const input = React.useRef<HTMLInputElement>(null);\n const search = useDebouncedCallback((query: string) => onSearch?.(query), debounce);\n const list = suggestions ?? [];\n\n const pick = (i: number) => {\n const suggestion = list[i];\n if (!suggestion) return;\n setOpen(false);\n onSuggestionSelect?.(suggestion);\n };\n const listbox = useListbox({ count: list.length, onPick: pick, open: open && list.length > 0, setOpen });\n\n React.useEffect(() => {\n if (!shortcut) return;\n // eslint-disable-next-line react-hooks/set-state-in-effect -- the platform is only known in the browser (no hydration mismatch)\n setApple(isApple());\n const onKey = (event: KeyboardEvent) => {\n if (event.key.toLowerCase() === shortcut.toLowerCase() && (event.metaKey || event.ctrlKey) && !event.altKey) {\n event.preventDefault();\n input.current?.focus();\n input.current?.select();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [shortcut]);\n\n const change = (query: string) => {\n setValue(query);\n search(query);\n listbox.setActive(-1);\n setOpen(true);\n };\n\n const field = (\n <div className={s.root({ className })} onBlur={(event) => !event.currentTarget.contains(event.relatedTarget as Node | null) && setOpen(false)}>\n <div className={s.control()}>\n <SearchGlyph className={s.icon()} />\n <input\n ref={input}\n type=\"search\"\n aria-label={label}\n enterKeyHint=\"search\"\n autoComplete=\"off\"\n {...(list.length > 0 ? listbox.inputProps : {})}\n value={value}\n placeholder={placeholder}\n className={s.input()}\n onChange={(event) => change(event.target.value)}\n onFocus={() => setOpen(true)}\n onKeyDown={(event) => {\n if (list.length > 0 && listbox.onKeyDown(event)) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n search.cancel();\n onSearch?.(value);\n onSubmit?.(value);\n setOpen(false);\n } else if (event.key === \"Escape\" && value) {\n event.preventDefault();\n change(\"\");\n }\n }}\n {...props}\n />\n {value ? (\n <button\n type=\"button\"\n aria-label={clearLabel}\n className={s.clear()}\n onClick={() => {\n change(\"\");\n input.current?.focus();\n }}\n >\n <CloseGlyph className=\"h-4 w-4\" />\n </button>\n ) : shortcut ? (\n <span className={s.shortcut()} aria-hidden>\n <Kbd size=\"sm\">{apple ? \"⌘\" : \"Ctrl\"}</Kbd>\n <Kbd size=\"sm\">{shortcut.toUpperCase()}</Kbd>\n </span>\n ) : null}\n </div>\n {list.length > 0 && (\n <div hidden={!open} className={s.list()}>\n {suggestionsLabel ? (\n <div aria-hidden className={s.group()}>\n {suggestionsLabel}\n </div>\n ) : null}\n <div id={listbox.listId} role=\"listbox\" aria-label={suggestionsLabel ?? label}>\n {list.map((suggestion, i) => (\n <div key={suggestion.value} {...listbox.optionProps(i, false)} className={s.option()}>\n <SearchGlyph className=\"h-3.5 w-3.5 shrink-0 text-fg-muted\" />\n <span className=\"min-w-0 flex-1 truncate\">{suggestion.label}</span>\n {suggestion.meta ? <span className=\"shrink-0 text-xs text-fg-secondary\">{suggestion.meta}</span> : null}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n return landmark ? <div role=\"search\">{field}</div> : field;\n}\n","// Server-safe. A key, or a shortcut of several (`<Kbd>⌘</Kbd><Kbd>K</Kbd>`).\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const kbdVariants = tv({\n base:\n \"inline-flex shrink-0 items-center justify-center rounded-md border border-border-default border-b-2 bg-surface-2 \" +\n \"font-mono font-semibold text-fg-secondary\",\n variants: { size: { sm: \"h-5 min-w-5 px-1 text-[10px]\", md: \"h-6 min-w-6 px-1.5 text-xs\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type KbdProps = React.ComponentProps<\"kbd\"> & {\n /**\n * sm · md.\n * @default \"md\"\n */\n size?: VariantProps<typeof kbdVariants>[\"size\"];\n};\n\nexport function Kbd({ size, className, ...props }: KbdProps) {\n return <kbd className={kbdVariants({ size, className })} {...props} />;\n}\n"],"mappings":"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","names":["tv","jsx","tv"]}