@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
package/dist/blocks.css CHANGED
@@ -94,6 +94,76 @@
94
94
  :is([data-surface="product"], .brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza) :is(.kz-heading-title, .kz-hero-title) {
95
95
  font-weight: 650; /* the serif had one weight; the sans carries the hierarchy with a semibold */
96
96
  }
97
+
98
+ /* ─── The product register, 2027 (ADR-006, krizaka-ui#669) ─────────────────────────────────────────────────────────
99
+ The calm look of the products: slate ink, translucent hairlines, a visible edge on every field, radius 14 on cards, an
100
+ interactive card that answers the hand. Only here: the Cahier sites (www, the blog, ui., java., ts., motion) keep
101
+ ADR-004 (paper, square corners, the quiet hover). The register is a product's ROOT — `data-surface="product"`, or its
102
+ `.brand-<id>` on `<html>` / `<body>`; a `.brand-<id>` wrapper inside a Cahier page (www's product cards, the docs'
103
+ examples) only lends its accent and stays Cahier. Both themes in one rule: `light-dark()` follows the `color-scheme` the tokens pin on `:root`,
104
+ `html.light`, `.theme-dark` and `.theme-light`, so a dark island in a light product stays dark.
105
+ Text roles are ≥ 4.5:1 and the control edge ≥ 3:1 on surfaces 0–2 (product-register.test.ts); a hairline is a
106
+ decoration (1.16:1) and never a field's only edge. `:root:is()` outranks `html.light`; the second selector keeps the
107
+ register inside a theme island of a product. The card rules below read `--kz-card-*`, set here and nowhere else. */
108
+ :is([data-surface="product"], :root:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza), body:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza)), :is([data-surface="product"], :root:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza), body:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza)) :is(.theme-dark, .theme-light) {
109
+ --kz-surface-0: light-dark(#fbfbfa, #111318);
110
+ --kz-surface-1: light-dark(#ffffff, #171a21);
111
+ --kz-surface-2: light-dark(#f4f4f2, #1e222b);
112
+ --kz-surface-3: light-dark(#f0f0ed, #272c37);
113
+ --kz-text-title: light-dark(#222a3a, #f3f5f9);
114
+ --kz-text-primary: light-dark(#242c3d, #e8ebf1);
115
+ --kz-text-secondary: light-dark(#576275, #a9b1bf);
116
+ --kz-text-muted: light-dark(#646d80, #959eae);
117
+ --kz-border-subtle: light-dark(rgb(28 40 65 / 0.04), rgb(255 255 255 / 0.04));
118
+ --kz-border-default: light-dark(rgb(28 40 65 / 0.08), rgb(255 255 255 / 0.08));
119
+ --kz-border-control: light-dark(#7d8799, #646d7e);
120
+ --kz-border-hover: light-dark(color-mix(in srgb, var(--kz-accent) 22%, transparent), color-mix(in srgb, var(--kz-accent) 30%, transparent));
121
+ --kz-shadow-hover: 0 10px 25px -5px light-dark(rgb(0 0 0 / 0.04), rgb(0 0 0 / 0.5));
122
+ --kz-radius-xs: 4px;
123
+ --kz-radius-sm: 8px;
124
+ --kz-radius-md: 8px;
125
+ --kz-radius-lg: 14px;
126
+ --kz-radius-xl: 14px;
127
+ --kz-radius-2xl: 14px;
128
+ --kz-card-radius: var(--kz-radius-lg);
129
+ --kz-card-hover-shadow: var(--kz-shadow-hover);
130
+ --kz-card-hover-transform: translateY(-1px);
131
+ /* The faces (ADR-006 §2, #670): Plus Jakarta Sans for the titles, Courier Prime for the identifiers and tabular meta
132
+ (« KZ-03 », a reference, a time); code keeps the system monospace and the pen (Krizaka Cahier) is never inside a
133
+ product. The display steps take 550 / 650 and the tracking of a large title (−0.015 em from 24 px, −0.022 em from 40 px);
134
+ the page title and a statistic's value take 700 below. Going back is one token: --kz-font-display: var(--kz-font-sans). */
135
+ --kz-font-display: var(--kz-font-product-display);
136
+ --kz-type-display-2xl-weight: 550;
137
+ --kz-type-display-xl-weight: 550;
138
+ --kz-type-display-lg-weight: 550;
139
+ --kz-type-display-md-weight: 650;
140
+ --kz-type-display-sm-weight: 650;
141
+ --kz-type-display-2xl-tracking: -0.022em;
142
+ --kz-type-display-xl-tracking: -0.022em;
143
+ --kz-type-display-lg-tracking: -0.022em;
144
+ --kz-type-display-md-tracking: -0.015em;
145
+ --kz-type-display-sm-tracking: -0.015em;
146
+ }
147
+ /* Titles at 700 (PageHeader's title, Stat's value) in the title ink. */
148
+ :is([data-surface="product"], :root:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza), body:is(.brand-orazaka, .brand-orochia, .brand-yasakia, .brand-yororis, .brand-yomizaka, .brand-kachizaka, .brand-akinaza)) :is(.kz-page-title, .kz-stat-value) { font-weight: 700; color: var(--kz-text-title); }
149
+ /* The hover of an INTERACTIVE card only (a link or a button; ADR-006 amends ADR-003 here): the brand border, a soft shadow
150
+ and a 1 px lift in 150 ms. A static card never moves, nothing moves under reduced motion (the border and the shadow
151
+ still answer), a button keeps its colour-only hover. The Cahier sets none of the `--kz-card-hover-*`: it stays quiet. */
152
+ .kz-link-card, a.kz-block-card, button.kz-block-card, [data-interactive] {
153
+ transition: transform 150ms var(--kz-ease, ease), box-shadow 150ms var(--kz-ease, ease), border-color 150ms var(--kz-ease, ease), background-color 150ms var(--kz-ease, ease);
154
+ }
155
+ @media (hover: hover) {
156
+ .kz-link-card:hover, a.kz-block-card:hover, button.kz-block-card:hover, [data-interactive]:hover {
157
+ border-color: var(--kz-border-hover);
158
+ box-shadow: var(--kz-card-hover-shadow, none);
159
+ transform: var(--kz-card-hover-transform, none);
160
+ }
161
+ }
162
+ @media (prefers-reduced-motion: reduce) {
163
+ .kz-link-card, a.kz-block-card, button.kz-block-card, [data-interactive] { transition: none; }
164
+ .kz-link-card:hover, a.kz-block-card:hover, button.kz-block-card:hover, [data-interactive]:hover { transform: none; }
165
+ }
166
+
97
167
  /* Cahier (ADR-004, #417): the eyebrow is a note in the margin's voice — the typewriter face, lower case, untracked,
98
168
  inked in the margin red. No more uppercase tracked overline above every heading. */
99
169
  .kz-eyebrow {
@@ -429,12 +499,12 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
429
499
  .kz-foundation { --kz-rail: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 50%, var(--kz-border-default)); display: grid; }
430
500
  .kz-foundation-base { position: relative; display: grid; min-width: 0; }
431
501
  .kz-foundation-base::after { content: ""; position: absolute; left: 50%; top: 100%; width: 1px; height: 28px; background: var(--kz-rail); }
432
- .kz-foundation-group { position: relative; margin-top: 28px; padding: 22px 14px 14px; border: 1px solid var(--kz-rail); border-radius: 0; }
502
+ .kz-foundation-group { position: relative; margin-top: 28px; padding: 22px 14px 14px; border: 1px solid var(--kz-rail); border-radius: var(--kz-card-radius, 0); }
433
503
  .kz-foundation-label { position: absolute; top: -9px; left: 22px; padding: 0 8px; font: 500 11px/18px var(--kz-font-mono, ui-monospace, monospace); letter-spacing: 0; text-transform: none; color: var(--kz-hue-text, var(--kz-accent-text)); background: var(--kz-surface-0); }
434
504
  .kz-foundation[data-position="end"] .kz-foundation-base { order: 2; }
435
505
  .kz-foundation[data-position="end"] .kz-foundation-group { order: 1; margin-top: 0; margin-bottom: 28px; }
436
506
  .kz-foundation[data-position="end"] .kz-foundation-base::after { top: auto; bottom: 100%; }
437
- @media (max-width: 640px) { .kz-foundation-group { padding: 20px 8px 8px; border-radius: 0; } }
507
+ @media (max-width: 640px) { .kz-foundation-group { padding: 20px 8px 8px; border-radius: var(--kz-card-radius, 0); } }
438
508
 
439
509
  /* The shared surface of the cards: a rail of the hue along the top, and one quiet hover (krizaka-ui#393) — the surface
440
510
  goes one step up and the hairline strengthens, in a short colour transition. Nothing moves, nothing follows the
@@ -443,7 +513,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
443
513
  position: relative;
444
514
  isolation: isolate;
445
515
  overflow: hidden;
446
- border-radius: 0;
516
+ border-radius: var(--kz-card-radius, 0);
447
517
  background: var(--kz-surface-1);
448
518
  border: 1px solid var(--kz-border-default);
449
519
  transition: background-color 150ms var(--kz-ease, ease), border-color 150ms var(--kz-ease, ease);
@@ -646,7 +716,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
646
716
 
647
717
  /* ─── DecisionList: one card per decision — what was chosen, large; refused · because · what it costs, side by side ─── */
648
718
  .kz-decisions { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; }
649
- .kz-decision { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 18px; padding: 20px 22px; border-radius: 0; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
719
+ .kz-decision { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 18px; padding: 20px 22px; border-radius: var(--kz-card-radius, 0); background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
650
720
  .kz-decision-n { font-family: var(--kz-font-display); font-size: 28px; font-weight: 400; line-height: 1; letter-spacing: -0.01em; font-variant-numeric: var(--kz-figures, lining-nums tabular-nums); color: var(--kz-hue-text, var(--kz-accent-text)); }
651
721
  .kz-decision-body { display: grid; gap: 14px; min-width: 0; }
652
722
  .kz-decision-part p:not(.kz-label) { margin: 6px 0 0; font-size: 14px; line-height: 1.6; color: var(--kz-text-secondary); }
@@ -664,7 +734,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
664
734
  @media (max-width: 560px) { .kz-decision { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 18px; } .kz-decision-n { font-size: 22px; } }
665
735
 
666
736
  /* ─── CodeBlock · CodeTabs: a file name, code that scrolls sideways (never shrinks), a copy button ─── */
667
- .kz-code { margin: 0; min-width: 0; overflow: hidden; border-radius: 0; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); box-shadow: inset 3px 0 0 var(--kz-hue, var(--kz-accent)); }
737
+ .kz-code { margin: 0; min-width: 0; overflow: hidden; border-radius: var(--kz-card-radius, 0); background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); box-shadow: inset 3px 0 0 var(--kz-hue, var(--kz-accent)); }
668
738
  .kz-code-bar {
669
739
  display: flex;
670
740
  align-items: center;
@@ -707,7 +777,9 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
707
777
  .kz-code .kz-line-dim, .kz-code pre[data-focus] .th-line:not(.kz-line-focus) { color: var(--kz-text-secondary); }
708
778
  .kz-code .kz-line-dim .th-token, .kz-code pre[data-focus] .th-line:not(.kz-line-focus) .th-token { color: inherit; font-weight: inherit; }
709
779
  /* Markdown (TanStack Markdown's AST on the tokens): reading text, nothing decorative. */
710
- .kz-md { min-width: 0; color: var(--kz-text-primary); font-size: 15px; line-height: 1.7; overflow-wrap: anywhere; }
780
+ .kz-md { min-width: 0; color: var(--kz-text-primary); font-size: 15px; line-height: 1.7; overflow-wrap: break-word; }
781
+ .kz-md :is(p, li, a, th, td) { overflow-wrap: break-word; }
782
+ .kz-md pre { white-space: pre; overflow-wrap: normal; }
711
783
  .kz-md > * { margin-block: 0; }
712
784
  .kz-md > * + * { margin-top: 0.9em; }
713
785
  .kz-md h1, .kz-md h2, .kz-md h3, .kz-md h4, .kz-md h5, .kz-md h6 { font-family: var(--kz-font-display); font-weight: 400; line-height: 1.2; letter-spacing: -0.01em; }
@@ -725,9 +797,24 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
725
797
  .kz-md :not(pre) > code { padding: 0.12em 0.4em; border-radius: 6px; font-family: var(--kz-font-mono); font-size: 0.88em; background: var(--kz-surface-3); }
726
798
  .kz-md hr { border: 0; border-top: 1px solid var(--kz-border-default); }
727
799
  .kz-md img { max-width: 100%; height: auto; border-radius: 0; }
728
- .kz-md-table { overflow-x: auto; }
729
- .kz-md-table table { width: 100%; border-collapse: collapse; font-size: 0.93em; }
800
+ .kz-md-table {
801
+ overflow-x: auto;
802
+ border: 1px solid var(--kz-border-subtle);
803
+ background:
804
+ linear-gradient(to right, var(--kz-surface-1) 30%, transparent) left / 32px 100%,
805
+ linear-gradient(to left, var(--kz-surface-1) 30%, transparent) right / 32px 100%,
806
+ linear-gradient(to right, color-mix(in srgb, var(--kz-text-primary) 20%, transparent), transparent) left / 10px 100%,
807
+ linear-gradient(to left, color-mix(in srgb, var(--kz-text-primary) 20%, transparent), transparent) right / 10px 100%;
808
+ background-color: var(--kz-surface-1);
809
+ background-repeat: no-repeat;
810
+ background-attachment: local, local, scroll, scroll;
811
+ }
812
+ .kz-md-table:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: -2px; }
813
+ .kz-md-table table { width: max-content; min-width: 100%; border-collapse: collapse; font-size: 0.93em; }
730
814
  .kz-md-table :is(th, td) { padding: 0.55em 0.8em; text-align: start; border-bottom: 1px solid var(--kz-border-subtle); }
815
+ .kz-md-cell { display: inline-block; vertical-align: top; width: max-content; min-width: min-content; max-width: 36ch; }
816
+ .kz-md-table :is(th, td):first-child { width: 1%; white-space: nowrap; }
817
+ .kz-md-table :is(th, td) code { white-space: nowrap; }
731
818
  .kz-md-table th { font-weight: 700; color: var(--kz-text-secondary); background: var(--kz-surface-2); }
732
819
  .kz-md [data-footnotes] { font-size: 0.9em; color: var(--kz-text-secondary); border-top: 1px solid var(--kz-border-subtle); padding-top: 0.8em; }
733
820
  /* A text still arriving: a caret where it goes on (still under reduced motion). */
@@ -795,7 +882,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
795
882
  justify-content: space-between;
796
883
  gap: 20px;
797
884
  padding: 24px 26px;
798
- border-radius: 0;
885
+ border-radius: var(--kz-card-radius, 0);
799
886
  background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 8%, var(--kz-surface-1));
800
887
  border: 1px solid color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 30%, var(--kz-border-default));
801
888
  }
@@ -837,7 +924,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
837
924
  .kz-tpl-split[data-reverse] > :first-child { order: 2; }
838
925
  @media (max-width: 900px) { .kz-tpl-split { grid-template-columns: minmax(0, 1fr); } .kz-tpl-split[data-reverse] > :first-child { order: 0; } }
839
926
  .kz-tpl-stage {
840
- position: relative; min-width: 0; overflow: hidden; border-radius: 0; border: 1px solid var(--kz-border-default); background: var(--kz-surface-1);
927
+ position: relative; min-width: 0; overflow: hidden; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); background: var(--kz-surface-1);
841
928
  box-shadow: var(--kz-shadow-md);
842
929
  }
843
930
  .kz-tpl-stage-bar { display: flex; align-items: center; gap: 6px; padding: 9px 12px; border-bottom: 1px solid var(--kz-border-subtle); background: var(--kz-surface-2);
@@ -856,7 +943,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
856
943
 
857
944
  /* A bento: features of different weights on a six-column grid (one column on a phone). */
858
945
  .kz-tpl-bento { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 14px; }
859
- .kz-tpl-bento > li { grid-column: span 2; display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 22px; border-radius: 0;
946
+ .kz-tpl-bento > li { grid-column: span 2; display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 22px; border-radius: var(--kz-card-radius, 0);
860
947
  background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
861
948
  .kz-tpl-bento > li[data-size="lg"] { grid-column: span 4; grid-row: span 2; background: color-mix(in srgb, var(--kz-hue, var(--kz-accent)) 7%, var(--kz-surface-1)); }
862
949
  .kz-tpl-bento > li[data-size="md"] { grid-column: span 3; }
@@ -888,7 +975,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
888
975
  /* A gallery: media in columns of different heights, the featured one wide. */
889
976
  .kz-tpl-gallery { margin: 0; padding: 0; list-style: none; columns: 3 280px; column-gap: 14px; }
890
977
  .kz-tpl-gallery > li { break-inside: avoid; margin-bottom: 14px; }
891
- .kz-tpl-figure { margin: 0; overflow: hidden; border-radius: 0; border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
978
+ .kz-tpl-figure { margin: 0; overflow: hidden; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
892
979
  .kz-tpl-figure-media { overflow: hidden; background: var(--kz-media); }
893
980
  .kz-tpl-figure-media > :is(img, video) { display: block; width: 100%; height: auto; }
894
981
  .kz-tpl-figure figcaption { display: grid; gap: 4px; padding: 12px 14px; }
@@ -901,7 +988,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
901
988
  .kz-tpl-hub-search > * { width: 100%; }
902
989
  .kz-tpl-hub-hints { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; font-size: 13px; color: var(--kz-text-secondary); }
903
990
  .kz-tpl-collections { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 14px; }
904
- .kz-tpl-collection { position: relative; isolation: isolate; overflow: hidden; display: flex; flex-direction: column; gap: 12px; height: 100%; padding: 20px; border-radius: 0;
991
+ .kz-tpl-collection { position: relative; isolation: isolate; overflow: hidden; display: flex; flex-direction: column; gap: 12px; height: 100%; padding: 20px; border-radius: var(--kz-card-radius, 0);
905
992
  background: linear-gradient(160deg, color-mix(in srgb, var(--kz-accent) 14%, var(--kz-surface-1)), var(--kz-surface-1) 55%);
906
993
  border: 1px solid color-mix(in srgb, var(--kz-accent) 28%, var(--kz-border-default)); }
907
994
  .kz-tpl-collection-head { display: flex; align-items: center; gap: 10px; }
@@ -959,7 +1046,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
959
1046
  .kz-tpl-count { margin: 0; font-family: var(--kz-font-mono); font-size: 12px; color: var(--kz-text-secondary); }
960
1047
  @media (max-width: 900px) {
961
1048
  .kz-tpl-catalogue { grid-template-columns: minmax(0, 1fr); gap: 16px; }
962
- .kz-tpl-catalogue-filters { position: static; border-radius: 0; border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
1049
+ .kz-tpl-catalogue-filters { position: static; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
963
1050
  .kz-tpl-catalogue-filters > summary { display: flex; align-items: center; justify-content: space-between; min-height: 44px; padding: 0 14px; cursor: pointer; list-style: none;
964
1051
  font-size: 14px; font-weight: 650; color: var(--kz-text-primary); }
965
1052
  .kz-tpl-catalogue-filters > summary::-webkit-details-marker { display: none; }
@@ -1017,7 +1104,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1017
1104
  /* Contact: the ways to reach us beside the form; what happens next under it. */
1018
1105
  .kz-tpl-contact { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: clamp(24px, 4vw, 48px); align-items: start; }
1019
1106
  @media (max-width: 900px) { .kz-tpl-contact { grid-template-columns: minmax(0, 1fr); } }
1020
- .kz-tpl-form { padding: clamp(18px, 3vw, 28px); border-radius: 0; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
1107
+ .kz-tpl-form { padding: clamp(18px, 3vw, 28px); border-radius: var(--kz-card-radius, 0); background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
1021
1108
  .kz-tpl-next { margin: 0; padding: 0; list-style: none; counter-reset: next; display: grid; gap: 12px; }
1022
1109
  .kz-tpl-next li { counter-increment: next; display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 12px; font-size: 14px; line-height: 1.6; color: var(--kz-text-secondary); }
1023
1110
  .kz-tpl-next li::before { content: counter(next); display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%;
@@ -1025,7 +1112,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1025
1112
  .kz-tpl-next strong { display: block; color: var(--kz-text-primary); }
1026
1113
 
1027
1114
  /* Status: one line per service, its state in words and a dot; an incident log under it. */
1028
- .kz-tpl-state { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 20px; padding: 18px 20px; border-radius: 0; border: 1px solid var(--kz-border-default);
1115
+ .kz-tpl-state { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 20px; padding: 18px 20px; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default);
1029
1116
  background: var(--kz-surface-1); }
1030
1117
  .kz-tpl-state[data-state="operational"] { border-color: color-mix(in srgb, var(--kz-success) 40%, var(--kz-border-default)); background: color-mix(in srgb, var(--kz-success) 7%, var(--kz-surface-1)); }
1031
1118
  .kz-tpl-state[data-state="degraded"] { border-color: color-mix(in srgb, var(--kz-warning) 40%, var(--kz-border-default)); background: color-mix(in srgb, var(--kz-warning) 7%, var(--kz-surface-1)); }
@@ -1036,7 +1123,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1036
1123
  [data-state="degraded"] > .kz-tpl-dot, .kz-tpl-dot[data-state="degraded"] { background: var(--kz-warning); }
1037
1124
  [data-state="outage"] > .kz-tpl-dot, .kz-tpl-dot[data-state="outage"] { background: var(--kz-danger); }
1038
1125
  [data-state="building"] > .kz-tpl-dot, .kz-tpl-dot[data-state="building"] { background: var(--kz-info); }
1039
- .kz-tpl-services { margin: 16px 0 0; padding: 0; list-style: none; border-radius: 0; border: 1px solid var(--kz-border-default); overflow: hidden; }
1126
+ .kz-tpl-services { margin: 16px 0 0; padding: 0; list-style: none; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); overflow: hidden; }
1040
1127
  .kz-tpl-services li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px; border-top: 1px solid var(--kz-border-subtle);
1041
1128
  font-size: 14.5px; color: var(--kz-text-primary); background: var(--kz-surface-1); }
1042
1129
  .kz-tpl-services li:first-child { border-top: 0; }
@@ -1052,7 +1139,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1052
1139
 
1053
1140
  /* Pricing: plans side by side, the featured one lifted; a comparison under them. */
1054
1141
  .kz-tpl-plans { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: 14px; align-items: stretch; }
1055
- .kz-tpl-plan { position: relative; display: flex; flex-direction: column; gap: 14px; height: 100%; padding: 24px; border-radius: 0; background: var(--kz-surface-1);
1142
+ .kz-tpl-plan { position: relative; display: flex; flex-direction: column; gap: 14px; height: 100%; padding: 24px; border-radius: var(--kz-card-radius, 0); background: var(--kz-surface-1);
1056
1143
  border: 1px solid var(--kz-border-default); }
1057
1144
  .kz-tpl-plan[data-featured] { border-color: var(--kz-accent); background: linear-gradient(170deg, color-mix(in srgb, var(--kz-accent) 12%, var(--kz-surface-1)), var(--kz-surface-1) 60%);
1058
1145
  box-shadow: var(--kz-shadow-md); }
@@ -1067,9 +1154,9 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1067
1154
  .kz-tpl-compare th, .kz-tpl-compare td { padding: 12px 14px; text-align: left; border-bottom: 1px solid var(--kz-border-subtle); color: var(--kz-text-secondary); }
1068
1155
  .kz-tpl-compare thead th { font-family: var(--kz-font-mono); font-size: 11px; letter-spacing: 0; text-transform: none; }
1069
1156
  .kz-tpl-compare tbody th { color: var(--kz-text-primary); font-weight: 600; }
1070
- .kz-tpl-scroll { overflow-x: auto; border-radius: 0; border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
1157
+ .kz-tpl-scroll { overflow-x: auto; border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
1071
1158
  .kz-tpl-faq { display: grid; gap: 8px; }
1072
- .kz-tpl-faq details { border-radius: 0; border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
1159
+ .kz-tpl-faq details { border-radius: var(--kz-card-radius, 0); border: 1px solid var(--kz-border-default); background: var(--kz-surface-1); }
1073
1160
  .kz-tpl-faq summary { display: flex; align-items: center; min-height: 48px; padding: 0 16px; cursor: pointer; list-style: none; font-size: 15px; font-weight: 650; color: var(--kz-text-primary); }
1074
1161
  .kz-tpl-faq summary::-webkit-details-marker { display: none; }
1075
1162
  .kz-tpl-faq summary:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; border-radius: 0; }
@@ -1175,23 +1262,71 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
1175
1262
  --kz-tape-w: clamp(54px, 8vw, 92px); --kz-tape-h: clamp(17px, 2.4vw, 26px);
1176
1263
  padding: clamp(7px, 1.2vw, 14px); background: var(--kz-print); transform: rotate(var(--kz-taped-tilt, -1.6deg)); transform-origin: 50% 60%;
1177
1264
  box-shadow: 0 1px 0 hsl(30 20% 8% / 0.22), 2px 4px 0 hsl(30 20% 8% / 0.14), 4px 8px 0 -2px hsl(30 20% 8% / 0.08); }
1265
+ .kz-stuck-body { --kz-tape: hsl(46 58% 82% / 0.72); --kz-tape-w: clamp(54px, 8vw, 92px); --kz-tape-h: clamp(17px, 2.4vw, 26px); }
1178
1266
  :root:not(.light) .kz-taped { --kz-print: hsl(42 22% 88%); --kz-tape: hsl(46 40% 70% / 0.62); }
1179
- .kz-taped::before, .kz-taped::after { content: ""; position: absolute; z-index: 1; width: var(--kz-tape-w); height: var(--kz-tape-h); background: var(--kz-tape);
1267
+ :root:not(.light) .kz-stuck-body { --kz-tape: hsl(46 40% 70% / 0.62); }
1268
+ /* Stuck's tape is this tape: the same strip, the same torn ends — one rule, two selectors. */
1269
+ .kz-taped::before, .kz-taped::after, .kz-stuck-body:is([data-hold="tape"], [data-hold="tape-corners"])::before, .kz-stuck-body:is([data-hold="tape"], [data-hold="tape-corners"])::after { content: ""; position: absolute; z-index: 1; width: var(--kz-tape-w); height: var(--kz-tape-h); background: var(--kz-tape);
1180
1270
  box-shadow: 0 1px 0 hsl(30 20% 8% / 0.2); pointer-events: none;
1181
1271
  clip-path: polygon(0 8%, 4% 0, 8% 10%, 12% 0, 100% 0, 96% 25%, 100% 50%, 96% 75%, 100% 100%, 12% 100%, 8% 90%, 4% 100%, 0 92%); }
1182
- .kz-taped::before { top: calc(-0.55 * var(--kz-tape-h)); left: calc(-0.35 * var(--kz-tape-w)); transform: rotate(-34deg); }
1183
- .kz-taped::after { bottom: calc(-0.55 * var(--kz-tape-h)); right: calc(-0.35 * var(--kz-tape-w)); transform: rotate(-34deg); }
1184
- .kz-taped[data-tape="top"]::before { top: calc(-0.5 * var(--kz-tape-h)); left: calc(50% - var(--kz-tape-w) / 2); transform: rotate(-3deg); }
1185
- .kz-taped[data-tape="top"]::after, .kz-taped[data-tape="none"]::before, .kz-taped[data-tape="none"]::after { display: none; }
1272
+ .kz-taped::before, .kz-stuck-body[data-hold="tape-corners"]::before { top: calc(-0.55 * var(--kz-tape-h)); left: calc(-0.35 * var(--kz-tape-w)); transform: rotate(-34deg); }
1273
+ .kz-taped::after, .kz-stuck-body[data-hold="tape-corners"]::after { bottom: calc(-0.55 * var(--kz-tape-h)); right: calc(-0.35 * var(--kz-tape-w)); transform: rotate(-34deg); }
1274
+ .kz-taped[data-tape="top"]::before, .kz-stuck-body[data-hold="tape"]::before { top: calc(-0.5 * var(--kz-tape-h)); left: calc(50% - var(--kz-tape-w) / 2); transform: rotate(-3deg); }
1275
+ .kz-taped[data-tape="top"]::after, .kz-taped[data-tape="none"]::before, .kz-taped[data-tape="none"]::after, .kz-stuck-body[data-hold="tape"]::after { display: none; }
1186
1276
  .kz-taped-picture { position: relative; overflow: hidden; }
1187
1277
  .kz-taped-picture > img, .kz-taped-picture > video { display: block; width: 100%; height: auto; }
1188
1278
  .kz-taped-caption { margin: 0; padding: 10px 4px 2px; font-family: var(--kz-font-mono); font-size: 13px; line-height: 20px; color: var(--kz-print-ink); }
1189
1279
  @media (max-width: 640px) {
1190
1280
  .kz-taped { transform: rotate(calc(var(--kz-taped-tilt, -1.6deg) * 0.6)); }
1191
- .kz-taped::before { left: -4px; } .kz-taped::after { right: -4px; }
1192
- .kz-taped[data-tape="top"]::before { left: calc(50% - var(--kz-tape-w) / 2); }
1281
+ .kz-taped::before, .kz-stuck-body[data-hold="tape-corners"]::before { left: -4px; } .kz-taped::after, .kz-stuck-body[data-hold="tape-corners"]::after { right: -4px; }
1282
+ .kz-taped[data-tape="top"]::before, .kz-stuck-body[data-hold="tape"]::before { left: calc(50% - var(--kz-tape-w) / 2); }
1193
1283
  }
1194
1284
 
1285
+ /* ─── Stuck (ADR-004): any block stuck into the notebook — held by tape (TapedPhoto's, above), a pin, photo corners or a
1286
+ lifted edge. The outer element stays still (it carries the doodles); the body leans by `--kz-stuck-tilt` (a transform:
1287
+ nothing shifts) on the hard paper shadow. A TapedPhoto or a SpecimenTag inside gives its own lean, shadow and tape up. ─── */
1288
+ .kz-stuck { position: relative; }
1289
+ .kz-stuck-body { position: relative; transform: rotate(var(--kz-stuck-tilt, 0deg)); transform-origin: 50% 60%; --kz-stuck-fold: var(--kz-paper-tag); --kz-stuck-metal: var(--kz-paper-tag-edge);
1290
+ box-shadow: var(--kz-shadow-floating); }
1291
+ .kz-stuck-body > :is(.kz-taped, .kz-tag) { transform: none; box-shadow: none; }
1292
+ .kz-stuck-body > .kz-taped::before, .kz-stuck-body > .kz-taped::after { display: none; }
1293
+ .kz-stuck-pin { position: absolute; z-index: 2; top: -7px; left: calc(50% - 7px); width: 14px; height: 14px; border-radius: 9999px; pointer-events: none;
1294
+ background: var(--kz-paper-rule-margin); box-shadow: inset -2px -2px 0 var(--kz-edge-well), var(--kz-shadow-floating); }
1295
+ .kz-stuck-body[data-hold="corner"]::before { content: ""; position: absolute; z-index: 1; inset: -3px; pointer-events: none;
1296
+ background:
1297
+ linear-gradient(135deg, var(--kz-stuck-fold) 50%, transparent 50%) top left / 18px 18px no-repeat,
1298
+ linear-gradient(225deg, var(--kz-stuck-fold) 50%, transparent 50%) top right / 18px 18px no-repeat,
1299
+ linear-gradient(315deg, var(--kz-stuck-fold) 50%, transparent 50%) bottom right / 18px 18px no-repeat,
1300
+ linear-gradient(45deg, var(--kz-stuck-fold) 50%, transparent 50%) bottom left / 18px 18px no-repeat; }
1301
+ .kz-stuck-body[data-hold="glue"]::after { content: ""; position: absolute; z-index: 1; right: 0; bottom: 0; width: 20px; height: 20px; pointer-events: none;
1302
+ background: linear-gradient(135deg, transparent 50%, var(--kz-stuck-fold) 50%); box-shadow: -2px -2px 0 var(--kz-stuck-metal); }
1303
+ @media (max-width: 640px) { .kz-stuck-body { transform: rotate(calc(var(--kz-stuck-tilt, 0deg) * 0.6)); } }
1304
+
1305
+ /* ─── Doodle (ADR-004): a margin doodle — in the margin ink, never over text. Beside the block only where the page's margin
1306
+ is wide enough to hold it (1360 px and up); below that it is gone (`place="inline"` stays in the flow). ─── */
1307
+ .kz-doodle { display: none; position: relative; width: 56px; color: var(--kz-paper-rule-margin); pointer-events: none; transform: rotate(var(--kz-doodle-tilt, 0deg)); }
1308
+ .kz-doodle[data-place="inline"] { display: inline-block; }
1309
+ .kz-doodle svg { display: block; width: 100%; height: auto; overflow: visible; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
1310
+ .kz-doodle[data-side="right"] svg { transform: scaleX(-1); }
1311
+ .kz-doodle[data-kind="circle"] { width: 72px; }
1312
+ .kz-doodle-word { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--kz-font-cahier, var(--kz-font-display)); font-size: 18px; line-height: 24px; color: var(--kz-text-secondary); }
1313
+ @media (min-width: 1360px) {
1314
+ .kz-doodle[data-place="margin"] { display: block; position: absolute; top: var(--kz-doodle-top, 0px); right: calc(100% + 16px); }
1315
+ .kz-doodle[data-place="margin"][data-side="right"] { right: auto; left: calc(100% + 16px); }
1316
+ .kz-stuck:has(> .kz-doodle[data-place="margin"][data-side="left"]) { margin-left: 96px; width: calc(100% - 96px); }
1317
+ .kz-stuck:has(> .kz-doodle[data-place="margin"][data-side="right"]) { margin-right: 96px; width: calc(100% - 96px); }
1318
+ .kz-stuck:has(> .kz-doodle[data-place="margin"][data-side="left"]):has(> .kz-doodle[data-place="margin"][data-side="right"]) { width: calc(100% - 192px); }
1319
+ }
1320
+
1321
+ /* ─── Signature (ADR-004): the house signs the page — the mark as an ink stamp, the name in the notebook's pen, one ink
1322
+ (the host's text role: chalk on slate, ink on paper), a slight grain from the SVG filter. Fixed sizes: nothing shifts. ─── */
1323
+ .kz-signature { position: relative; display: inline-flex; align-items: center; gap: 14px; color: var(--kz-text-primary); }
1324
+ .kz-signature-defs { position: absolute; width: 0; height: 0; }
1325
+ .kz-signature-stamp { flex: none; width: 48px; height: 48px; transform: rotate(-6deg); }
1326
+ .kz-signature-text { display: grid; gap: 2px; transform: rotate(-2deg); transform-origin: 0 100%; }
1327
+ .kz-signature-name { font-family: var(--kz-font-cahier, var(--kz-font-display)); font-size: 26px; line-height: 32px; white-space: nowrap; }
1328
+ .kz-signature-date { font-family: var(--kz-font-mono); font-size: 12px; line-height: 16px; color: var(--kz-text-secondary); }
1329
+
1195
1330
  .kz-plate, .kz-anatomy {
1196
1331
  margin: 0;
1197
1332
  padding: 20px 24px 24px;
package/dist/chat.js CHANGED
@@ -17,10 +17,10 @@ var chat = tv({
17
17
  typing: "inline-flex items-center gap-1 self-start rounded-2xl bg-surface-2 px-3.5 py-3",
18
18
  dot: "h-[7px] w-[7px] rounded-full bg-fg-secondary motion-safe:animate-[kz-typing_1.2s_ease-in-out_infinite]",
19
19
  composer: "flex items-end gap-2 border-t border-border-subtle bg-surface-0 px-3 py-2",
20
- input: "max-h-32 min-h-10 flex-1 resize-none rounded-2xl border border-border-default bg-surface-1 px-3.5 py-2.5 text-sm text-fg placeholder:text-fg-muted focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
20
+ input: "max-h-32 min-h-10 flex-1 resize-none rounded-2xl border border-border-control bg-surface-1 px-3.5 py-2.5 text-sm text-fg placeholder:text-fg-muted focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
21
21
  send: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent hover:bg-accent-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:bg-surface-3 disabled:text-fg-muted [&>svg]:h-[18px] [&>svg]:w-[18px]",
22
22
  pillRoot: "flex w-full flex-col gap-2",
23
- pill: "flex items-end gap-1.5 rounded-[1.75rem] border border-border-default bg-surface-1 py-1.5 pl-2 pr-1.5 transition-colors focus-within:border-accent focus-within:ring-2 focus-within:ring-ring",
23
+ pill: "flex items-end gap-1.5 rounded-[1.75rem] border border-border-control bg-surface-1 py-1.5 pl-2 pr-1.5 transition-colors focus-within:border-accent focus-within:ring-2 focus-within:ring-ring",
24
24
  pillLeading: "flex min-h-9 shrink-0 items-center gap-1 self-end",
25
25
  pillInput: "max-h-32 min-h-9 min-w-0 flex-1 resize-none border-0 bg-transparent px-1.5 py-[7px] text-sm leading-snug text-fg placeholder:text-fg-muted focus:outline-hidden focus-visible:outline-hidden",
26
26
  pillSend: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent shadow-sm transition-colors hover:bg-accent-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-1 disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-fg-muted disabled:shadow-none [&>svg]:h-4 [&>svg]:w-4",
package/dist/chat.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/chat/chat.tsx"],"sourcesContent":["// Client (the composer's draft). A conversation's parts — the bubble with its time and receipt, the typing dots, the\n// composer, a conversation in a list — the same API as React Native. Words are props.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Avatar } from \"../avatar\";\n\nexport const chat = tv({\n slots: {\n row: \"flex flex-col gap-0.5\",\n bubble: \"max-w-[80%] rounded-2xl px-3 py-2 text-sm leading-snug\",\n context: \"mb-0.5 block text-xs opacity-85\",\n time: \"mt-0.5 block text-right text-[11px] tabular-nums\",\n status: \"flex items-center gap-1 text-xs text-fg-secondary data-[status=failed]:text-fg-danger [&>svg]:h-3.5 [&>svg]:w-3.5\",\n typing: \"inline-flex items-center gap-1 self-start rounded-2xl bg-surface-2 px-3.5 py-3\",\n dot: \"h-[7px] w-[7px] rounded-full bg-fg-secondary motion-safe:animate-[kz-typing_1.2s_ease-in-out_infinite]\",\n composer: \"flex items-end gap-2 border-t border-border-subtle bg-surface-0 px-3 py-2\",\n input:\n \"max-h-32 min-h-10 flex-1 resize-none rounded-2xl border border-border-default bg-surface-1 px-3.5 py-2.5 text-sm text-fg placeholder:text-fg-muted \" +\n \"focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n send:\n \"inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent hover:bg-accent-hover focus-visible:outline-hidden \" +\n \"focus-visible:ring-2 focus-visible:ring-ring disabled:bg-surface-3 disabled:text-fg-muted [&>svg]:h-[18px] [&>svg]:w-[18px]\",\n pillRoot: \"flex w-full flex-col gap-2\",\n pill:\n \"flex items-end gap-1.5 rounded-[1.75rem] border border-border-default bg-surface-1 py-1.5 pl-2 pr-1.5 transition-colors \" +\n \"focus-within:border-accent focus-within:ring-2 focus-within:ring-ring\",\n pillLeading: \"flex min-h-9 shrink-0 items-center gap-1 self-end\",\n pillInput:\n \"max-h-32 min-h-9 min-w-0 flex-1 resize-none border-0 bg-transparent px-1.5 py-[7px] text-sm leading-snug text-fg placeholder:text-fg-muted \" +\n \"focus:outline-hidden focus-visible:outline-hidden\",\n pillSend:\n \"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent shadow-sm transition-colors hover:bg-accent-hover \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-1 \" +\n \"disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-fg-muted disabled:shadow-none [&>svg]:h-4 [&>svg]:w-4\",\n pillStatus: \"m-0 flex min-h-5 items-center gap-1.5 px-3 text-xs text-fg-secondary [&_svg]:h-3.5 [&_svg]:w-3.5 [&_svg]:shrink-0\",\n item: \"flex w-full items-center gap-3 px-4 py-2.5 text-left hover:bg-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\",\n count: \"inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-accent px-1.5 text-xs font-extrabold text-on-accent\",\n },\n});\n\nexport type MessageStatus = \"sending\" | \"sent\" | \"delivered\" | \"read\" | \"failed\";\n\nexport type MessageBubbleLabels = {\n /** The words of each status, shown under the last message of yours. */\n status?: Partial<Record<MessageStatus, string>>;\n /** A failed message's retry button (“Retry”). */\n retry?: string;\n};\n\nconst STATUS: Record<MessageStatus, string> = { sending: \"Sending\", sent: \"Sent\", delivered: \"Delivered\", read: \"Read\", failed: \"Not sent\" };\n\nexport type MessageBubbleProps = {\n /** The text. */\n text: string;\n /** Yours (right, in the accent) or theirs (left). */\n mine?: boolean;\n /** The time, written by the app (“14:02”). */\n time?: string;\n /** Where a message of yours stands; shown when `showStatus`. */\n status?: MessageStatus;\n /** Show the status under the bubble (the last message of yours). */\n showStatus?: boolean;\n /** A line above the text: what it answers. */\n context?: string;\n /** Sends a failed message again (a button under it). */\n onRetry?: () => void;\n /** Part of a run of the same sender: the corner towards the next one is tighter. */\n grouped?: \"first\" | \"middle\" | \"last\" | \"single\";\n /** The words, passed translated. */\n labels?: MessageBubbleLabels;\n /** Classes merged on the row. */\n className?: string;\n};\n\nconst CORNERS = {\n mine: { first: \"rounded-br-md\", middle: \"rounded-r-md\", last: \"rounded-tr-md\", single: \"\" },\n theirs: { first: \"rounded-bl-md\", middle: \"rounded-l-md\", last: \"rounded-tl-md\", single: \"\" },\n} as const;\n\n/** A message: yours in the accent on the right, theirs on the left, the time inside, the receipt under the last of yours. */\nexport function MessageBubble({ text, mine, time, status, showStatus, context, onRetry, grouped = \"single\", labels, className }: MessageBubbleProps) {\n const s = chat();\n const words = { ...STATUS, ...labels?.status };\n return (\n <div className={s.row({ className: [mine ? \"items-end\" : \"items-start\", className].filter(Boolean).join(\" \") })}>\n <p\n className={s.bubble({\n className: [mine ? \"bg-accent text-on-accent\" : \"bg-surface-2 text-fg\", CORNERS[mine ? \"mine\" : \"theirs\"][grouped], status === \"failed\" ? \"ring-2 ring-danger\" : \"\", status === \"sending\" ? \"opacity-70\" : \"\"].join(\" \"),\n })}\n >\n {context ? <span className={s.context()}>{context}</span> : null}\n {text}\n {time ? <span className={s.time()}>{time}</span> : null}\n </p>\n {showStatus && status ? (\n <p className={s.status()} data-status={status}>\n {status === \"sent\" || status === \"delivered\" || status === \"read\" ? (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className={status === \"read\" ? \"stroke-accent\" : \"stroke-fg-secondary\"}>\n <path d={status === \"sent\" ? \"M5 12.5l4.5 4.5L19 7.5\" : \"M2 12.5l4.5 4.5L16 7.5M9 15l2 2 9.5-9.5\"} />\n </svg>\n ) : null}\n {words[status]}\n {status === \"failed\" && onRetry ? (\n <button type=\"button\" onClick={onRetry} className=\"ml-1 font-semibold text-fg underline underline-offset-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\">\n {labels?.retry ?? \"Retry\"}\n </button>\n ) : null}\n </p>\n ) : null}\n </div>\n );\n}\n\nexport type TypingIndicatorProps = {\n /** What is read and shown beside the dots (“Elena is typing”) — passed translated. */\n label: string;\n /** Show the words beside the dots. */\n showLabel?: boolean;\n /** Classes merged on the root. */\n className?: string;\n};\n\n/** Three dots that breathe while the other person types, announced politely; still under reduced motion. */\nexport function TypingIndicator({ label, showLabel, className }: TypingIndicatorProps) {\n const s = chat();\n return (\n <div role=\"status\" className={[\"flex items-center gap-2\", className].filter(Boolean).join(\" \")}>\n <style href=\"krizaka-typing\" precedence=\"default\">{\"@keyframes kz-typing{0%,60%,100%{opacity:.35;transform:none}30%{opacity:1;transform:translateY(-2px)}}\"}</style>\n <span className={s.typing()} aria-hidden>\n {[0, 1, 2].map((i) => (\n <span key={i} className={s.dot()} style={{ animationDelay: `${i * 0.18}s` }} />\n ))}\n </span>\n <span className={showLabel ? \"text-xs text-fg-secondary\" : \"sr-only\"}>{label}</span>\n </div>\n );\n}\n\nexport type MessageComposerProps = {\n /** The draft (controlled). */\n value: string;\n /** Called on every key. */\n onValueChange: (text: string) => void;\n /** Sends the draft (Enter, or the button); Shift+Enter adds a line. */\n onSend: () => void;\n /** The input's name and placeholder (“Message”). */\n placeholder: string;\n /** The send button's name (“Send”). */\n sendLabel: string;\n /** Before the input: an attach button (`bar`), or the mode/model chip and attach, inside the field (`pill`). */\n leading?: React.ReactNode;\n /** Cannot write: the reason in its place. */\n disabledReason?: string;\n /** The longest message. Default 4000. */\n maxLength?: number;\n /** `bar`: a docked bar with a square-ish field. `pill`: one rounded field holding `leading`, the text and a round send button — no inner border. Default `bar`. */\n variant?: \"bar\" | \"pill\";\n /** `pill`: the quiet line under the field (privacy, cost estimate). Its row is always reserved, so a changing line never moves the field. Read politely. */\n status?: React.ReactNode;\n /** An answer is on its way: the send is held (and `aria-busy` is set) while the field stays where it is, size included. */\n busy?: boolean;\n /** Overrides “the draft has text” — e.g. an attachment alone can be sent. A busy composer never sends. */\n canSend?: boolean;\n /** Attributes (`data-testid`, `autoFocus`, `id`…) forwarded to the textarea. */\n inputProps?: Omit<React.ComponentPropsWithoutRef<\"textarea\">, \"value\" | \"onChange\" | \"placeholder\" | \"maxLength\" | \"className\" | \"rows\">;\n /** Attributes forwarded to the send button. */\n sendProps?: Omit<React.ComponentPropsWithoutRef<\"button\">, \"type\" | \"disabled\" | \"className\" | \"aria-label\">;\n /** Classes merged on the root. */\n className?: string;\n};\n\n/** Where a message is written: a growing textarea (Enter sends, Shift+Enter a new line), an attach slot, a send button. The `pill` variant is the one-field look of the Krizaka chat card. */\nexport function MessageComposer({\n value,\n onValueChange,\n onSend,\n placeholder,\n sendLabel,\n leading,\n disabledReason,\n maxLength = 4000,\n variant = \"bar\",\n status,\n busy = false,\n canSend,\n inputProps,\n sendProps,\n className,\n}: MessageComposerProps) {\n const s = chat();\n const pill = variant === \"pill\";\n const ready = !busy && (canSend ?? value.trim().length > 0);\n const textarea = (\n <textarea\n aria-label={placeholder}\n placeholder={placeholder}\n rows={1}\n maxLength={maxLength}\n {...inputProps}\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n inputProps?.onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (e.key === \"Enter\" && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n if (ready) onSend();\n }\n }}\n className={pill ? s.pillInput() : s.input()}\n style={{ fieldSizing: \"content\" } as React.CSSProperties}\n />\n );\n const send = (\n <button type=\"submit\" aria-label={sendLabel} {...sendProps} disabled={!ready} className={pill ? s.pillSend() : s.send()}>\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden>\n <path d=\"M4 12l16-8-6 16-2.5-6.5L4 12z\" />\n </svg>\n </button>\n );\n const submit = (e: React.FormEvent) => {\n e.preventDefault();\n if (ready) onSend();\n };\n if (pill) {\n return (\n <form className={s.pillRoot({ className })} onSubmit={submit} aria-busy={busy || undefined}>\n {disabledReason ? (\n <p className=\"m-0 rounded-[1.75rem] border border-border-default bg-surface-1 px-4 py-2.5 text-sm text-fg-secondary\">{disabledReason}</p>\n ) : (\n <div className={s.pill()}>\n {leading ? <div className={s.pillLeading()}>{leading}</div> : null}\n {textarea}\n {send}\n </div>\n )}\n <p role=\"status\" aria-live=\"polite\" className={s.pillStatus()}>\n {status}\n </p>\n </form>\n );\n }\n return (\n <form className={s.composer({ className })} onSubmit={submit} aria-busy={busy || undefined}>\n {disabledReason ? (\n <p className=\"m-0 flex-1 py-2 text-sm text-fg-secondary\">{disabledReason}</p>\n ) : (\n <>\n {leading}\n {textarea}\n {send}\n </>\n )}\n </form>\n );\n}\n\nexport type ConversationItemProps = {\n /** The other person's name. */\n name: string;\n /** Their avatar's URL. */\n avatar?: string | null;\n /** The last message, or “typing…”. */\n preview: string;\n /** The preview is the typing signal: in the accent. */\n typing?: boolean;\n /** When (“14:02”, “Mon”). */\n time?: string;\n /** Unread messages: a count, the name in bold. */\n unread?: number;\n /** The unread count in words (“3 unread”). */\n unreadLabel?: string;\n /** Before the name: a presence dot (online). */\n online?: boolean;\n /** The presence in words (“online”). */\n onlineLabel?: string;\n /** Opens the conversation (a link). */\n href?: string;\n /** Opens the conversation (a button). */\n onSelect?: () => void;\n /** Classes merged on the row. */\n className?: string;\n};\n\n/** A conversation in the list: avatar, name, the last message or typing, the time, the unread count. */\nexport function ConversationItem({ name, avatar, preview, typing, time, unread = 0, unreadLabel, online, onlineLabel, href, onSelect, className }: ConversationItemProps) {\n const s = chat();\n const body = (\n <>\n <span className=\"relative shrink-0\">\n <Avatar src={avatar ?? null} alt=\"\" fallback={name.charAt(0)} size=\"lg\" />\n {online ? <span aria-hidden className=\"absolute bottom-0 right-0 h-3 w-3 rounded-full bg-success ring-2 ring-surface-0\" /> : null}\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"flex items-center gap-2\">\n <span className={[\"min-w-0 flex-1 truncate text-sm text-fg\", unread > 0 ? \"font-extrabold\" : \"font-semibold\"].join(\" \")}>\n {name}\n {online && onlineLabel ? <span className=\"sr-only\">{`, ${onlineLabel}`}</span> : null}\n </span>\n {time ? <span className={[\"shrink-0 text-xs tabular-nums\", unread > 0 ? \"text-fg-accent\" : \"text-fg-secondary\"].join(\" \")}>{time}</span> : null}\n </span>\n <span className=\"flex items-center gap-2\">\n <span className={[\"min-w-0 flex-1 truncate text-xs\", typing ? \"text-fg-accent\" : unread > 0 ? \"text-fg\" : \"text-fg-secondary\"].join(\" \")}>{preview}</span>\n {unread > 0 ? (\n <span className={s.count()}>\n <span aria-hidden>{unread > 99 ? \"99+\" : unread}</span>\n <span className=\"sr-only\">{unreadLabel ?? String(unread)}</span>\n </span>\n ) : null}\n </span>\n </span>\n </>\n );\n return href ? (\n <a href={href} className={s.item({ className })}>\n {body}\n </a>\n ) : (\n <button type=\"button\" onClick={onSelect} className={s.item({ className })}>\n {body}\n </button>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/chat/chat.tsx"],"sourcesContent":["// Client (the composer's draft). A conversation's parts — the bubble with its time and receipt, the typing dots, the\n// composer, a conversation in a list — the same API as React Native. Words are props.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Avatar } from \"../avatar\";\n\nexport const chat = tv({\n slots: {\n row: \"flex flex-col gap-0.5\",\n bubble: \"max-w-[80%] rounded-2xl px-3 py-2 text-sm leading-snug\",\n context: \"mb-0.5 block text-xs opacity-85\",\n time: \"mt-0.5 block text-right text-[11px] tabular-nums\",\n status: \"flex items-center gap-1 text-xs text-fg-secondary data-[status=failed]:text-fg-danger [&>svg]:h-3.5 [&>svg]:w-3.5\",\n typing: \"inline-flex items-center gap-1 self-start rounded-2xl bg-surface-2 px-3.5 py-3\",\n dot: \"h-[7px] w-[7px] rounded-full bg-fg-secondary motion-safe:animate-[kz-typing_1.2s_ease-in-out_infinite]\",\n composer: \"flex items-end gap-2 border-t border-border-subtle bg-surface-0 px-3 py-2\",\n input:\n \"max-h-32 min-h-10 flex-1 resize-none rounded-2xl border border-border-control bg-surface-1 px-3.5 py-2.5 text-sm text-fg placeholder:text-fg-muted \" +\n \"focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n send:\n \"inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent hover:bg-accent-hover focus-visible:outline-hidden \" +\n \"focus-visible:ring-2 focus-visible:ring-ring disabled:bg-surface-3 disabled:text-fg-muted [&>svg]:h-[18px] [&>svg]:w-[18px]\",\n pillRoot: \"flex w-full flex-col gap-2\",\n pill:\n \"flex items-end gap-1.5 rounded-[1.75rem] border border-border-control bg-surface-1 py-1.5 pl-2 pr-1.5 transition-colors \" +\n \"focus-within:border-accent focus-within:ring-2 focus-within:ring-ring\",\n pillLeading: \"flex min-h-9 shrink-0 items-center gap-1 self-end\",\n pillInput:\n \"max-h-32 min-h-9 min-w-0 flex-1 resize-none border-0 bg-transparent px-1.5 py-[7px] text-sm leading-snug text-fg placeholder:text-fg-muted \" +\n \"focus:outline-hidden focus-visible:outline-hidden\",\n pillSend:\n \"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent shadow-sm transition-colors hover:bg-accent-hover \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-1 \" +\n \"disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-fg-muted disabled:shadow-none [&>svg]:h-4 [&>svg]:w-4\",\n pillStatus: \"m-0 flex min-h-5 items-center gap-1.5 px-3 text-xs text-fg-secondary [&_svg]:h-3.5 [&_svg]:w-3.5 [&_svg]:shrink-0\",\n item: \"flex w-full items-center gap-3 px-4 py-2.5 text-left hover:bg-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\",\n count: \"inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-accent px-1.5 text-xs font-extrabold text-on-accent\",\n },\n});\n\nexport type MessageStatus = \"sending\" | \"sent\" | \"delivered\" | \"read\" | \"failed\";\n\nexport type MessageBubbleLabels = {\n /** The words of each status, shown under the last message of yours. */\n status?: Partial<Record<MessageStatus, string>>;\n /** A failed message's retry button (“Retry”). */\n retry?: string;\n};\n\nconst STATUS: Record<MessageStatus, string> = { sending: \"Sending\", sent: \"Sent\", delivered: \"Delivered\", read: \"Read\", failed: \"Not sent\" };\n\nexport type MessageBubbleProps = {\n /** The text. */\n text: string;\n /** Yours (right, in the accent) or theirs (left). */\n mine?: boolean;\n /** The time, written by the app (“14:02”). */\n time?: string;\n /** Where a message of yours stands; shown when `showStatus`. */\n status?: MessageStatus;\n /** Show the status under the bubble (the last message of yours). */\n showStatus?: boolean;\n /** A line above the text: what it answers. */\n context?: string;\n /** Sends a failed message again (a button under it). */\n onRetry?: () => void;\n /** Part of a run of the same sender: the corner towards the next one is tighter. */\n grouped?: \"first\" | \"middle\" | \"last\" | \"single\";\n /** The words, passed translated. */\n labels?: MessageBubbleLabels;\n /** Classes merged on the row. */\n className?: string;\n};\n\nconst CORNERS = {\n mine: { first: \"rounded-br-md\", middle: \"rounded-r-md\", last: \"rounded-tr-md\", single: \"\" },\n theirs: { first: \"rounded-bl-md\", middle: \"rounded-l-md\", last: \"rounded-tl-md\", single: \"\" },\n} as const;\n\n/** A message: yours in the accent on the right, theirs on the left, the time inside, the receipt under the last of yours. */\nexport function MessageBubble({ text, mine, time, status, showStatus, context, onRetry, grouped = \"single\", labels, className }: MessageBubbleProps) {\n const s = chat();\n const words = { ...STATUS, ...labels?.status };\n return (\n <div className={s.row({ className: [mine ? \"items-end\" : \"items-start\", className].filter(Boolean).join(\" \") })}>\n <p\n className={s.bubble({\n className: [mine ? \"bg-accent text-on-accent\" : \"bg-surface-2 text-fg\", CORNERS[mine ? \"mine\" : \"theirs\"][grouped], status === \"failed\" ? \"ring-2 ring-danger\" : \"\", status === \"sending\" ? \"opacity-70\" : \"\"].join(\" \"),\n })}\n >\n {context ? <span className={s.context()}>{context}</span> : null}\n {text}\n {time ? <span className={s.time()}>{time}</span> : null}\n </p>\n {showStatus && status ? (\n <p className={s.status()} data-status={status}>\n {status === \"sent\" || status === \"delivered\" || status === \"read\" ? (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className={status === \"read\" ? \"stroke-accent\" : \"stroke-fg-secondary\"}>\n <path d={status === \"sent\" ? \"M5 12.5l4.5 4.5L19 7.5\" : \"M2 12.5l4.5 4.5L16 7.5M9 15l2 2 9.5-9.5\"} />\n </svg>\n ) : null}\n {words[status]}\n {status === \"failed\" && onRetry ? (\n <button type=\"button\" onClick={onRetry} className=\"ml-1 font-semibold text-fg underline underline-offset-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\">\n {labels?.retry ?? \"Retry\"}\n </button>\n ) : null}\n </p>\n ) : null}\n </div>\n );\n}\n\nexport type TypingIndicatorProps = {\n /** What is read and shown beside the dots (“Elena is typing”) — passed translated. */\n label: string;\n /** Show the words beside the dots. */\n showLabel?: boolean;\n /** Classes merged on the root. */\n className?: string;\n};\n\n/** Three dots that breathe while the other person types, announced politely; still under reduced motion. */\nexport function TypingIndicator({ label, showLabel, className }: TypingIndicatorProps) {\n const s = chat();\n return (\n <div role=\"status\" className={[\"flex items-center gap-2\", className].filter(Boolean).join(\" \")}>\n <style href=\"krizaka-typing\" precedence=\"default\">{\"@keyframes kz-typing{0%,60%,100%{opacity:.35;transform:none}30%{opacity:1;transform:translateY(-2px)}}\"}</style>\n <span className={s.typing()} aria-hidden>\n {[0, 1, 2].map((i) => (\n <span key={i} className={s.dot()} style={{ animationDelay: `${i * 0.18}s` }} />\n ))}\n </span>\n <span className={showLabel ? \"text-xs text-fg-secondary\" : \"sr-only\"}>{label}</span>\n </div>\n );\n}\n\nexport type MessageComposerProps = {\n /** The draft (controlled). */\n value: string;\n /** Called on every key. */\n onValueChange: (text: string) => void;\n /** Sends the draft (Enter, or the button); Shift+Enter adds a line. */\n onSend: () => void;\n /** The input's name and placeholder (“Message”). */\n placeholder: string;\n /** The send button's name (“Send”). */\n sendLabel: string;\n /** Before the input: an attach button (`bar`), or the mode/model chip and attach, inside the field (`pill`). */\n leading?: React.ReactNode;\n /** Cannot write: the reason in its place. */\n disabledReason?: string;\n /** The longest message. Default 4000. */\n maxLength?: number;\n /** `bar`: a docked bar with a square-ish field. `pill`: one rounded field holding `leading`, the text and a round send button — no inner border. Default `bar`. */\n variant?: \"bar\" | \"pill\";\n /** `pill`: the quiet line under the field (privacy, cost estimate). Its row is always reserved, so a changing line never moves the field. Read politely. */\n status?: React.ReactNode;\n /** An answer is on its way: the send is held (and `aria-busy` is set) while the field stays where it is, size included. */\n busy?: boolean;\n /** Overrides “the draft has text” — e.g. an attachment alone can be sent. A busy composer never sends. */\n canSend?: boolean;\n /** Attributes (`data-testid`, `autoFocus`, `id`…) forwarded to the textarea. */\n inputProps?: Omit<React.ComponentPropsWithoutRef<\"textarea\">, \"value\" | \"onChange\" | \"placeholder\" | \"maxLength\" | \"className\" | \"rows\">;\n /** Attributes forwarded to the send button. */\n sendProps?: Omit<React.ComponentPropsWithoutRef<\"button\">, \"type\" | \"disabled\" | \"className\" | \"aria-label\">;\n /** Classes merged on the root. */\n className?: string;\n};\n\n/** Where a message is written: a growing textarea (Enter sends, Shift+Enter a new line), an attach slot, a send button. The `pill` variant is the one-field look of the Krizaka chat card. */\nexport function MessageComposer({\n value,\n onValueChange,\n onSend,\n placeholder,\n sendLabel,\n leading,\n disabledReason,\n maxLength = 4000,\n variant = \"bar\",\n status,\n busy = false,\n canSend,\n inputProps,\n sendProps,\n className,\n}: MessageComposerProps) {\n const s = chat();\n const pill = variant === \"pill\";\n const ready = !busy && (canSend ?? value.trim().length > 0);\n const textarea = (\n <textarea\n aria-label={placeholder}\n placeholder={placeholder}\n rows={1}\n maxLength={maxLength}\n {...inputProps}\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n inputProps?.onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (e.key === \"Enter\" && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n if (ready) onSend();\n }\n }}\n className={pill ? s.pillInput() : s.input()}\n style={{ fieldSizing: \"content\" } as React.CSSProperties}\n />\n );\n const send = (\n <button type=\"submit\" aria-label={sendLabel} {...sendProps} disabled={!ready} className={pill ? s.pillSend() : s.send()}>\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden>\n <path d=\"M4 12l16-8-6 16-2.5-6.5L4 12z\" />\n </svg>\n </button>\n );\n const submit = (e: React.FormEvent) => {\n e.preventDefault();\n if (ready) onSend();\n };\n if (pill) {\n return (\n <form className={s.pillRoot({ className })} onSubmit={submit} aria-busy={busy || undefined}>\n {disabledReason ? (\n <p className=\"m-0 rounded-[1.75rem] border border-border-default bg-surface-1 px-4 py-2.5 text-sm text-fg-secondary\">{disabledReason}</p>\n ) : (\n <div className={s.pill()}>\n {leading ? <div className={s.pillLeading()}>{leading}</div> : null}\n {textarea}\n {send}\n </div>\n )}\n <p role=\"status\" aria-live=\"polite\" className={s.pillStatus()}>\n {status}\n </p>\n </form>\n );\n }\n return (\n <form className={s.composer({ className })} onSubmit={submit} aria-busy={busy || undefined}>\n {disabledReason ? (\n <p className=\"m-0 flex-1 py-2 text-sm text-fg-secondary\">{disabledReason}</p>\n ) : (\n <>\n {leading}\n {textarea}\n {send}\n </>\n )}\n </form>\n );\n}\n\nexport type ConversationItemProps = {\n /** The other person's name. */\n name: string;\n /** Their avatar's URL. */\n avatar?: string | null;\n /** The last message, or “typing…”. */\n preview: string;\n /** The preview is the typing signal: in the accent. */\n typing?: boolean;\n /** When (“14:02”, “Mon”). */\n time?: string;\n /** Unread messages: a count, the name in bold. */\n unread?: number;\n /** The unread count in words (“3 unread”). */\n unreadLabel?: string;\n /** Before the name: a presence dot (online). */\n online?: boolean;\n /** The presence in words (“online”). */\n onlineLabel?: string;\n /** Opens the conversation (a link). */\n href?: string;\n /** Opens the conversation (a button). */\n onSelect?: () => void;\n /** Classes merged on the row. */\n className?: string;\n};\n\n/** A conversation in the list: avatar, name, the last message or typing, the time, the unread count. */\nexport function ConversationItem({ name, avatar, preview, typing, time, unread = 0, unreadLabel, online, onlineLabel, href, onSelect, className }: ConversationItemProps) {\n const s = chat();\n const body = (\n <>\n <span className=\"relative shrink-0\">\n <Avatar src={avatar ?? null} alt=\"\" fallback={name.charAt(0)} size=\"lg\" />\n {online ? <span aria-hidden className=\"absolute bottom-0 right-0 h-3 w-3 rounded-full bg-success ring-2 ring-surface-0\" /> : null}\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"flex items-center gap-2\">\n <span className={[\"min-w-0 flex-1 truncate text-sm text-fg\", unread > 0 ? \"font-extrabold\" : \"font-semibold\"].join(\" \")}>\n {name}\n {online && onlineLabel ? <span className=\"sr-only\">{`, ${onlineLabel}`}</span> : null}\n </span>\n {time ? <span className={[\"shrink-0 text-xs tabular-nums\", unread > 0 ? \"text-fg-accent\" : \"text-fg-secondary\"].join(\" \")}>{time}</span> : null}\n </span>\n <span className=\"flex items-center gap-2\">\n <span className={[\"min-w-0 flex-1 truncate text-xs\", typing ? \"text-fg-accent\" : unread > 0 ? \"text-fg\" : \"text-fg-secondary\"].join(\" \")}>{preview}</span>\n {unread > 0 ? (\n <span className={s.count()}>\n <span aria-hidden>{unread > 99 ? \"99+\" : unread}</span>\n <span className=\"sr-only\">{unreadLabel ?? String(unread)}</span>\n </span>\n ) : null}\n </span>\n </span>\n </>\n );\n return href ? (\n <a href={href} className={s.item({ className })}>\n {body}\n </a>\n ) : (\n <button type=\"button\" onClick={onSelect} className={s.item({ className })}>\n {body}\n </button>\n );\n}\n"],"mappings":"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","names":[]}
package/dist/checkbox.js CHANGED
@@ -6,7 +6,7 @@ import { tv } from "tailwind-variants";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  var checkbox = tv({
8
8
  slots: {
9
- root: "peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-strong bg-surface-1 text-on-accent transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent aria-invalid:border-danger aria-invalid:ring-danger/30",
9
+ root: "peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-control bg-surface-1 text-on-accent transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent aria-invalid:border-danger aria-invalid:ring-danger/30",
10
10
  indicator: "flex items-center justify-center",
11
11
  label: "flex cursor-pointer items-start gap-3 text-sm text-fg has-disabled:cursor-not-allowed has-disabled:opacity-70"
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/checkbox/checkbox.tsx"],"sourcesContent":["// Client. Radix Checkbox: role=\"checkbox\", aria-checked (true · false · mixed), Space toggles, a hidden input inside a\n// form. It sits in a `Field` like the other controls: `<Field.Label htmlFor={id}>`, `invalid`, aria-describedby.\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const checkbox = tv({\n slots: {\n root:\n \"peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-strong bg-surface-1 text-on-accent transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 \" +\n \"data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent \" +\n \"aria-invalid:border-danger aria-invalid:ring-danger/30\",\n indicator: \"flex items-center justify-center\",\n label: \"flex cursor-pointer items-start gap-3 text-sm text-fg has-disabled:cursor-not-allowed has-disabled:opacity-70\",\n },\n});\n\nfunction Check() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction Dash() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M5 12h14\" />\n </svg>\n );\n}\n\nexport type CheckboxProps = Omit<React.ComponentProps<typeof CheckboxPrimitive.Root>, \"children\"> & {\n /** Marks it invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n /** The text next to the box, clickable: the box and its words in one `<label>`. Otherwise name it with\n * `Field.Label htmlFor` or `aria-label`. */\n children?: React.ReactNode;\n};\n\n/** A checkbox: `checked`/`defaultChecked` (`true` · `false` · `\"indeterminate\"`) + `onCheckedChange`. */\nexport function Checkbox({ invalid, className, children, ...props }: CheckboxProps) {\n const s = checkbox();\n const box = (\n <CheckboxPrimitive.Root\n aria-invalid={invalid || undefined}\n data-invalid={invalid ? \"\" : undefined}\n className={s.root({ className: children ? \"mt-0.5\" : className })}\n {...props}\n >\n <CheckboxPrimitive.Indicator className={s.indicator()}>\n {props.checked === \"indeterminate\" ? <Dash /> : <Check />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n if (!children) return box;\n return (\n <label className={s.label({ className })}>\n {box}\n <span className=\"min-w-0\">{children}</span>\n </label>\n );\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,yBAAyB;AAE9C,SAAS,UAAU;AAkBb,cAsCF,YAtCE;AAhBC,IAAM,WAAW,GAAG;AAAA,EACzB,OAAO;AAAA,IACL,MACE;AAAA,IAKF,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AACF,CAAC;AAED,SAAS,QAAQ;AACf,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACzJ,8BAAC,UAAK,GAAE,mBAAkB,GAC5B;AAEJ;AAEA,SAAS,OAAO;AACd,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,eAAW,MAClI,8BAAC,UAAK,GAAE,YAAW,GACrB;AAEJ;AAWO,SAAS,SAAS,EAAE,SAAS,WAAW,UAAU,GAAG,MAAM,GAAkB;AAClF,QAAM,IAAI,SAAS;AACnB,QAAM,MACJ;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,gBAAc,WAAW;AAAA,MACzB,gBAAc,UAAU,KAAK;AAAA,MAC7B,WAAW,EAAE,KAAK,EAAE,WAAW,WAAW,WAAW,UAAU,CAAC;AAAA,MAC/D,GAAG;AAAA,MAEJ,8BAAC,kBAAkB,WAAlB,EAA4B,WAAW,EAAE,UAAU,GACjD,gBAAM,YAAY,kBAAkB,oBAAC,QAAK,IAAK,oBAAC,SAAM,GACzD;AAAA;AAAA,EACF;AAEF,MAAI,CAAC,SAAU,QAAO;AACtB,SACE,qBAAC,WAAM,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GACpC;AAAA;AAAA,IACD,oBAAC,UAAK,WAAU,WAAW,UAAS;AAAA,KACtC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/checkbox/checkbox.tsx"],"sourcesContent":["// Client. Radix Checkbox: role=\"checkbox\", aria-checked (true · false · mixed), Space toggles, a hidden input inside a\n// form. It sits in a `Field` like the other controls: `<Field.Label htmlFor={id}>`, `invalid`, aria-describedby.\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const checkbox = tv({\n slots: {\n root:\n \"peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-control bg-surface-1 text-on-accent transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 \" +\n \"data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent \" +\n \"aria-invalid:border-danger aria-invalid:ring-danger/30\",\n indicator: \"flex items-center justify-center\",\n label: \"flex cursor-pointer items-start gap-3 text-sm text-fg has-disabled:cursor-not-allowed has-disabled:opacity-70\",\n },\n});\n\nfunction Check() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction Dash() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M5 12h14\" />\n </svg>\n );\n}\n\nexport type CheckboxProps = Omit<React.ComponentProps<typeof CheckboxPrimitive.Root>, \"children\"> & {\n /** Marks it invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n /** The text next to the box, clickable: the box and its words in one `<label>`. Otherwise name it with\n * `Field.Label htmlFor` or `aria-label`. */\n children?: React.ReactNode;\n};\n\n/** A checkbox: `checked`/`defaultChecked` (`true` · `false` · `\"indeterminate\"`) + `onCheckedChange`. */\nexport function Checkbox({ invalid, className, children, ...props }: CheckboxProps) {\n const s = checkbox();\n const box = (\n <CheckboxPrimitive.Root\n aria-invalid={invalid || undefined}\n data-invalid={invalid ? \"\" : undefined}\n className={s.root({ className: children ? \"mt-0.5\" : className })}\n {...props}\n >\n <CheckboxPrimitive.Indicator className={s.indicator()}>\n {props.checked === \"indeterminate\" ? <Dash /> : <Check />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n if (!children) return box;\n return (\n <label className={s.label({ className })}>\n {box}\n <span className=\"min-w-0\">{children}</span>\n </label>\n );\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,yBAAyB;AAE9C,SAAS,UAAU;AAkBb,cAsCF,YAtCE;AAhBC,IAAM,WAAW,GAAG;AAAA,EACzB,OAAO;AAAA,IACL,MACE;AAAA,IAKF,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AACF,CAAC;AAED,SAAS,QAAQ;AACf,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACzJ,8BAAC,UAAK,GAAE,mBAAkB,GAC5B;AAEJ;AAEA,SAAS,OAAO;AACd,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,eAAW,MAClI,8BAAC,UAAK,GAAE,YAAW,GACrB;AAEJ;AAWO,SAAS,SAAS,EAAE,SAAS,WAAW,UAAU,GAAG,MAAM,GAAkB;AAClF,QAAM,IAAI,SAAS;AACnB,QAAM,MACJ;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,gBAAc,WAAW;AAAA,MACzB,gBAAc,UAAU,KAAK;AAAA,MAC7B,WAAW,EAAE,KAAK,EAAE,WAAW,WAAW,WAAW,UAAU,CAAC;AAAA,MAC/D,GAAG;AAAA,MAEJ,8BAAC,kBAAkB,WAAlB,EAA4B,WAAW,EAAE,UAAU,GACjD,gBAAM,YAAY,kBAAkB,oBAAC,QAAK,IAAK,oBAAC,SAAM,GACzD;AAAA;AAAA,EACF;AAEF,MAAI,CAAC,SAAU,QAAO;AACtB,SACE,qBAAC,WAAM,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GACpC;AAAA;AAAA,IACD,oBAAC,UAAK,WAAU,WAAW,UAAS;AAAA,KACtC;AAEJ;","names":[]}
package/dist/chip.js CHANGED
@@ -1,103 +1,10 @@
1
1
  "use client";
2
2
  import {
3
- useRouteBinding
4
- } from "./chunk-R3LTSMS5.js";
5
- import {
6
- defineRecipe
7
- } from "./chunk-D3T54RSL.js";
8
-
9
- // src/chip/chip.tsx
10
- import { Toggle as TogglePrimitive, ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
11
- import * as React from "react";
12
- import { tv } from "tailwind-variants";
13
-
14
- // src/chip/recipe.ts
15
- var chipRecipe = defineRecipe({
16
- slots: {
17
- group: "flex flex-wrap items-center gap-2 data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch",
18
- base: "inline-flex shrink-0 select-none items-center justify-center gap-1.5 whitespace-nowrap rounded-sm border font-semibold transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40 border-border-default bg-surface-1 text-fg-secondary hover:border-border-strong hover:text-fg data-[state=on]:border-accent data-[state=on]:bg-accent-soft data-[state=on]:text-fg",
19
- remove: "-mr-1.5 inline-flex h-6 w-6 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
20
- },
21
- variants: {
22
- size: { sm: { base: "h-7 px-3 text-xs" }, md: { base: "h-9 px-3.5 text-xs" } }
23
- },
24
- defaultVariants: { size: "md" }
25
- });
26
-
27
- // src/chip/chip.tsx
28
- import { jsx, jsxs } from "react/jsx-runtime";
29
- var chip = tv(chipRecipe);
30
- var ChipGroupContext = React.createContext(null);
31
- function RemoveIcon() {
32
- return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
33
- }
34
- function ChipBase(props) {
35
- const group = React.useContext(ChipGroupContext);
36
- if (props.removable) {
37
- const { removable: _removable2, removeLabel, onRemove, disabled, size: size2, className: className2, children, ...rest2 } = props;
38
- const s2 = chip({ size: size2 ?? group?.size });
39
- return /* @__PURE__ */ jsxs("span", { "data-removable": "", className: s2.base({ className: className2 }), ...rest2, children: [
40
- children,
41
- /* @__PURE__ */ jsx("button", { type: "button", "aria-label": removeLabel, title: removeLabel, disabled, onClick: onRemove, className: s2.remove(), children: /* @__PURE__ */ jsx(RemoveIcon, {}) })
42
- ] });
43
- }
44
- const { removable: _removable, value, selected, defaultSelected, onSelectedChange, size, className, ...rest } = props;
45
- const s = chip({ size: size ?? group?.size });
46
- if (group) {
47
- if (value === void 0) throw new Error("Chip: a chip inside Chip.Group needs a `value`.");
48
- return /* @__PURE__ */ jsx(ToggleGroupPrimitive.Item, { value, className: s.base({ className }), ...rest });
49
- }
50
- return /* @__PURE__ */ jsx(
51
- TogglePrimitive.Root,
52
- {
53
- pressed: selected,
54
- defaultPressed: defaultSelected,
55
- onPressedChange: onSelectedChange,
56
- className: s.base({ className }),
57
- ...rest
58
- }
59
- );
60
- }
61
- function ChipGroup({ label, size, className, children, ...props }) {
62
- const single = props.type === "single" ? props : void 0;
63
- const routed = useRouteBinding(single?.routeKey, single?.routeValues, { value: single?.value, defaultValue: single?.defaultValue, onValueChange: single?.onValueChange });
64
- const s = chip({ size });
65
- const context = React.useMemo(() => ({ size }), [size]);
66
- const common = { "aria-label": label, className: s.group({ className }) };
67
- let group;
68
- if (props.type === "single") {
69
- const { type: _type, value: _value, defaultValue: _defaultValue, onValueChange: _onValueChange, required, routeKey: _routeKey, routeValues: _routeValues, ...rest } = props;
70
- group = /* @__PURE__ */ jsx(SingleGroup, { ...rest, ...common, value: routed.value, defaultValue: routed.defaultValue, onValueChange: routed.onValueChange, required, children });
71
- } else {
72
- const { type: _type, required: _required, ...rest } = props;
73
- group = /* @__PURE__ */ jsx(ToggleGroupPrimitive.Root, { type: "multiple", ...rest, ...common, children });
74
- }
75
- return /* @__PURE__ */ jsx(ChipGroupContext.Provider, { value: context, children: group });
76
- }
77
- function SingleGroup({
78
- value,
79
- defaultValue,
80
- onValueChange,
81
- required,
82
- ...props
83
- }) {
84
- const [inner, setInner] = React.useState(defaultValue ?? "");
85
- const current = value ?? inner;
86
- return /* @__PURE__ */ jsx(
87
- ToggleGroupPrimitive.Root,
88
- {
89
- type: "single",
90
- value: current,
91
- onValueChange: (next) => {
92
- if (required && !next) return;
93
- if (value === void 0) setInner(next);
94
- onValueChange?.(next);
95
- },
96
- ...props
97
- }
98
- );
99
- }
100
- var Chip = Object.assign(ChipBase, { Group: ChipGroup });
3
+ Chip,
4
+ ChipGroup,
5
+ chip
6
+ } from "./chunk-7U5TXA5Q.js";
7
+ import "./chunk-D3T54RSL.js";
101
8
  export {
102
9
  Chip,
103
10
  ChipGroup,