@krizaka/ui 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. package/dist/activity-feed.d.ts +199 -0
  2. package/dist/activity-feed.js +155 -0
  3. package/dist/activity-feed.js.map +1 -0
  4. package/dist/argument-card.js +3 -3
  5. package/dist/{chunk-I5RVM5CW.js → chunk-2FRWNSRO.js} +2 -6
  6. package/dist/chunk-2FRWNSRO.js.map +1 -0
  7. package/dist/chunk-7Z4KHPFC.js +42 -0
  8. package/dist/chunk-7Z4KHPFC.js.map +1 -0
  9. package/dist/chunk-BTMFZ66D.js +135 -0
  10. package/dist/chunk-BTMFZ66D.js.map +1 -0
  11. package/dist/chunk-C2BRIFJG.js +13 -0
  12. package/dist/chunk-C2BRIFJG.js.map +1 -0
  13. package/dist/chunk-KDXRYUD3.js +39 -0
  14. package/dist/chunk-KDXRYUD3.js.map +1 -0
  15. package/dist/{chunk-2PUDI7JS.js → chunk-ZKVQGXLD.js} +5 -3
  16. package/dist/{chunk-2PUDI7JS.js.map → chunk-ZKVQGXLD.js.map} +1 -1
  17. package/dist/command.js +1 -1
  18. package/dist/confirm-button.js +1 -1
  19. package/dist/data-table.js +101 -133
  20. package/dist/data-table.js.map +1 -1
  21. package/dist/date-picker.d.ts +3 -1
  22. package/dist/date-picker.js +13 -13
  23. package/dist/date-picker.js.map +1 -1
  24. package/dist/description-list.d.ts +105 -0
  25. package/dist/description-list.js +49 -0
  26. package/dist/description-list.js.map +1 -0
  27. package/dist/dropdown-menu.js +1 -1
  28. package/dist/filter-bar.js +3 -2
  29. package/dist/form.d.ts +23 -12
  30. package/dist/form.js +11 -47
  31. package/dist/form.js.map +1 -1
  32. package/dist/glow-card.js +1 -1
  33. package/dist/image-cropper.js +3 -1
  34. package/dist/image-cropper.js.map +1 -1
  35. package/dist/index.js +13 -66
  36. package/dist/index.js.map +1 -1
  37. package/dist/kanban.d.ts +132 -0
  38. package/dist/kanban.js +187 -0
  39. package/dist/kanban.js.map +1 -0
  40. package/dist/list.d.ts +153 -0
  41. package/dist/list.js +130 -0
  42. package/dist/list.js.map +1 -0
  43. package/dist/map.d.ts +463 -0
  44. package/dist/map.js +952 -0
  45. package/dist/map.js.map +1 -0
  46. package/dist/marquee.js +1 -1
  47. package/dist/motion.css +12 -1
  48. package/dist/native/form.d.ts +60 -15
  49. package/dist/native/form.js +103 -42
  50. package/dist/native/form.js.map +1 -1
  51. package/dist/native/map.d.ts +200 -0
  52. package/dist/native/map.js +673 -0
  53. package/dist/native/map.js.map +1 -0
  54. package/dist/native/media-picker.d.ts +58 -0
  55. package/dist/native/media-picker.js +63 -0
  56. package/dist/native/media-picker.js.map +1 -0
  57. package/dist/native.d.ts +772 -6
  58. package/dist/native.js +2493 -741
  59. package/dist/native.js.map +1 -1
  60. package/dist/nav-bar.js +1 -1
  61. package/dist/page-hero.js +3 -3
  62. package/dist/popover.js +1 -1
  63. package/dist/radio-group.d.ts +66 -32
  64. package/dist/radio-group.js +54 -10
  65. package/dist/radio-group.js.map +1 -1
  66. package/dist/slider.d.ts +96 -35
  67. package/dist/slider.js +67 -13
  68. package/dist/slider.js.map +1 -1
  69. package/dist/stat.d.ts +31 -2
  70. package/dist/stat.js +21 -4
  71. package/dist/stat.js.map +1 -1
  72. package/dist/terminal-replay.js +34 -60
  73. package/dist/terminal-replay.js.map +1 -1
  74. package/dist/toast.js +1 -1
  75. package/dist/tooltip.js +1 -1
  76. package/dist/tree-view.d.ts +111 -0
  77. package/dist/tree-view.js +154 -0
  78. package/dist/tree-view.js.map +1 -0
  79. package/dist/video-player.js +3 -1
  80. package/dist/video-player.js.map +1 -1
  81. package/package.json +148 -11
  82. package/registry/achievement.json +1 -1
  83. package/registry/action-bar.json +1 -1
  84. package/registry/action-sheet.json +121 -0
  85. package/registry/activity-feed.json +468 -0
  86. package/registry/alert.json +1 -1
  87. package/registry/app-shell.json +1 -1
  88. package/registry/argument-card.json +1 -1
  89. package/registry/audio-player.json +1 -1
  90. package/registry/auth-layout.json +1 -1
  91. package/registry/avatar.json +58 -3
  92. package/registry/badge.json +1 -1
  93. package/registry/button.json +1 -1
  94. package/registry/card-grid.json +1 -1
  95. package/registry/card.json +1 -1
  96. package/registry/catalogue-page.json +1 -1
  97. package/registry/changelog-page.json +1 -1
  98. package/registry/checkbox.json +1 -1
  99. package/registry/chip-link.json +1 -1
  100. package/registry/chip.json +1 -1
  101. package/registry/choice-grid.json +1 -1
  102. package/registry/code-block.json +1 -1
  103. package/registry/combobox.json +226 -4
  104. package/registry/command.json +1 -1
  105. package/registry/component-page.json +1 -1
  106. package/registry/confirm-button.json +1 -1
  107. package/registry/contact-page.json +1 -1
  108. package/registry/continue-prompt.json +1 -1
  109. package/registry/countdown.json +1 -1
  110. package/registry/cta-panel.json +1 -1
  111. package/registry/dashboard-layout.json +1 -1
  112. package/registry/data-table.json +1 -1
  113. package/registry/date-picker.json +18 -4
  114. package/registry/decision-list.json +1 -1
  115. package/registry/description-list.json +232 -0
  116. package/registry/detail-layout.json +1 -1
  117. package/registry/dialog.json +75 -4
  118. package/registry/docs-article-page.json +1 -1
  119. package/registry/docs-hub-page.json +1 -1
  120. package/registry/docs-layout.json +1 -1
  121. package/registry/dropdown-menu.json +1 -1
  122. package/registry/empty-state.json +1 -1
  123. package/registry/error-page.json +1 -1
  124. package/registry/examples/action-sheet/native/video-actions.d.ts +4 -0
  125. package/registry/examples/action-sheet/native/video-actions.dark.png +0 -0
  126. package/registry/examples/action-sheet/native/video-actions.js +30 -0
  127. package/registry/examples/action-sheet/native/video-actions.light.png +0 -0
  128. package/registry/examples/action-sheet/native/video-actions.tsx +24 -0
  129. package/registry/examples/activity-feed/job-activity.d.ts +4 -0
  130. package/registry/examples/activity-feed/job-activity.js +21 -0
  131. package/registry/examples/activity-feed/job-activity.tsx +17 -0
  132. package/registry/examples/activity-feed/live.d.ts +4 -0
  133. package/registry/examples/activity-feed/live.js +23 -0
  134. package/registry/examples/activity-feed/live.tsx +24 -0
  135. package/registry/examples/activity-feed/native/notifications.d.ts +4 -0
  136. package/registry/examples/activity-feed/native/notifications.dark.png +0 -0
  137. package/registry/examples/activity-feed/native/notifications.js +18 -0
  138. package/registry/examples/activity-feed/native/notifications.light.png +0 -0
  139. package/registry/examples/activity-feed/native/notifications.tsx +18 -0
  140. package/registry/examples/activity-feed/timeline.d.ts +4 -0
  141. package/registry/examples/activity-feed/timeline.js +25 -0
  142. package/registry/examples/activity-feed/timeline.tsx +19 -0
  143. package/registry/examples/avatar/native/presence.d.ts +4 -0
  144. package/registry/examples/avatar/native/presence.dark.png +0 -0
  145. package/registry/examples/avatar/native/presence.js +18 -0
  146. package/registry/examples/avatar/native/presence.light.png +0 -0
  147. package/registry/examples/avatar/native/presence.tsx +15 -0
  148. package/registry/examples/combobox/native/multiple.d.ts +4 -0
  149. package/registry/examples/combobox/native/multiple.dark.png +0 -0
  150. package/registry/examples/combobox/native/multiple.js +15 -0
  151. package/registry/examples/combobox/native/multiple.light.png +0 -0
  152. package/registry/examples/combobox/native/multiple.tsx +15 -0
  153. package/registry/examples/combobox/native/search.d.ts +4 -0
  154. package/registry/examples/combobox/native/search.dark.png +0 -0
  155. package/registry/examples/combobox/native/search.js +15 -0
  156. package/registry/examples/combobox/native/search.light.png +0 -0
  157. package/registry/examples/combobox/native/search.tsx +15 -0
  158. package/registry/examples/description-list/job-details.d.ts +4 -0
  159. package/registry/examples/description-list/job-details.js +23 -0
  160. package/registry/examples/description-list/job-details.tsx +17 -0
  161. package/registry/examples/description-list/key-value-grid.d.ts +4 -0
  162. package/registry/examples/description-list/key-value-grid.js +22 -0
  163. package/registry/examples/description-list/key-value-grid.tsx +16 -0
  164. package/registry/examples/description-list/native/job-details.d.ts +4 -0
  165. package/registry/examples/description-list/native/job-details.dark.png +0 -0
  166. package/registry/examples/description-list/native/job-details.js +33 -0
  167. package/registry/examples/description-list/native/job-details.light.png +0 -0
  168. package/registry/examples/description-list/native/job-details.tsx +24 -0
  169. package/registry/examples/description-list/receipt.d.ts +4 -0
  170. package/registry/examples/description-list/receipt.js +23 -0
  171. package/registry/examples/description-list/receipt.tsx +17 -0
  172. package/registry/examples/dialog/native/sheet.d.ts +4 -0
  173. package/registry/examples/dialog/native/sheet.dark.png +0 -0
  174. package/registry/examples/dialog/native/sheet.js +21 -0
  175. package/registry/examples/dialog/native/sheet.light.png +0 -0
  176. package/registry/examples/dialog/native/sheet.tsx +18 -0
  177. package/registry/examples/fab/native/extended.d.ts +4 -0
  178. package/registry/examples/fab/native/extended.dark.png +0 -0
  179. package/registry/examples/fab/native/extended.js +18 -0
  180. package/registry/examples/fab/native/extended.light.png +0 -0
  181. package/registry/examples/fab/native/extended.tsx +23 -0
  182. package/registry/examples/field/native/select.d.ts +4 -0
  183. package/registry/examples/field/native/select.dark.png +0 -0
  184. package/registry/examples/field/native/select.js +29 -0
  185. package/registry/examples/field/native/select.light.png +0 -0
  186. package/registry/examples/field/native/select.tsx +25 -0
  187. package/registry/examples/form/native/audience.dark.png +0 -0
  188. package/registry/examples/form/native/audience.light.png +0 -0
  189. package/registry/examples/form/native/profile.dark.png +0 -0
  190. package/registry/examples/form/native/profile.light.png +0 -0
  191. package/registry/examples/form/native/settings.dark.png +0 -0
  192. package/registry/examples/form/native/settings.light.png +0 -0
  193. package/registry/examples/form/native/sign-up.dark.png +0 -0
  194. package/registry/examples/form/native/sign-up.light.png +0 -0
  195. package/registry/examples/form/native/upload.dark.png +0 -0
  196. package/registry/examples/form/native/upload.light.png +0 -0
  197. package/registry/examples/header/native/large-title.d.ts +4 -0
  198. package/registry/examples/header/native/large-title.dark.png +0 -0
  199. package/registry/examples/header/native/large-title.js +23 -0
  200. package/registry/examples/header/native/large-title.light.png +0 -0
  201. package/registry/examples/header/native/large-title.tsx +31 -0
  202. package/registry/examples/image-viewer/native/gallery.d.ts +4 -0
  203. package/registry/examples/image-viewer/native/gallery.dark.png +0 -0
  204. package/registry/examples/image-viewer/native/gallery.js +22 -0
  205. package/registry/examples/image-viewer/native/gallery.light.png +0 -0
  206. package/registry/examples/image-viewer/native/gallery.tsx +21 -0
  207. package/registry/examples/kanban/moderation.d.ts +4 -0
  208. package/registry/examples/kanban/moderation.js +35 -0
  209. package/registry/examples/kanban/moderation.tsx +37 -0
  210. package/registry/examples/list/jobs.d.ts +4 -0
  211. package/registry/examples/list/jobs.js +35 -0
  212. package/registry/examples/list/jobs.tsx +33 -0
  213. package/registry/examples/list/selectable.d.ts +4 -0
  214. package/registry/examples/list/selectable.js +33 -0
  215. package/registry/examples/list/selectable.tsx +30 -0
  216. package/registry/examples/list/virtualized.d.ts +4 -0
  217. package/registry/examples/list/virtualized.js +22 -0
  218. package/registry/examples/list/virtualized.tsx +17 -0
  219. package/registry/examples/loader/native/block.d.ts +4 -0
  220. package/registry/examples/loader/native/block.dark.png +0 -0
  221. package/registry/examples/loader/native/block.js +12 -0
  222. package/registry/examples/loader/native/block.light.png +0 -0
  223. package/registry/examples/loader/native/block.tsx +11 -0
  224. package/registry/examples/loader/native/job-wait.d.ts +4 -0
  225. package/registry/examples/loader/native/job-wait.dark.png +0 -0
  226. package/registry/examples/loader/native/job-wait.js +17 -0
  227. package/registry/examples/loader/native/job-wait.light.png +0 -0
  228. package/registry/examples/loader/native/job-wait.tsx +14 -0
  229. package/registry/examples/map/cluster.d.ts +4 -0
  230. package/registry/examples/map/cluster.js +16 -0
  231. package/registry/examples/map/cluster.tsx +18 -0
  232. package/registry/examples/map/location-picker.d.ts +4 -0
  233. package/registry/examples/map/location-picker.js +24 -0
  234. package/registry/examples/map/location-picker.tsx +22 -0
  235. package/registry/examples/map/native/location-picker.d.ts +4 -0
  236. package/registry/examples/map/native/location-picker.dark.png +0 -0
  237. package/registry/examples/map/native/location-picker.js +14 -0
  238. package/registry/examples/map/native/location-picker.light.png +0 -0
  239. package/registry/examples/map/native/location-picker.tsx +13 -0
  240. package/registry/examples/map/native/places.d.ts +4 -0
  241. package/registry/examples/map/native/places.dark.png +0 -0
  242. package/registry/examples/map/native/places.js +25 -0
  243. package/registry/examples/map/native/places.light.png +0 -0
  244. package/registry/examples/map/native/places.tsx +27 -0
  245. package/registry/examples/map/places.d.ts +4 -0
  246. package/registry/examples/map/places.js +28 -0
  247. package/registry/examples/map/places.tsx +28 -0
  248. package/registry/examples/map/static.d.ts +4 -0
  249. package/registry/examples/map/static.js +22 -0
  250. package/registry/examples/map/static.tsx +18 -0
  251. package/registry/examples/media-picker/native/story.d.ts +4 -0
  252. package/registry/examples/media-picker/native/story.dark.png +0 -0
  253. package/registry/examples/media-picker/native/story.js +30 -0
  254. package/registry/examples/media-picker/native/story.light.png +0 -0
  255. package/registry/examples/media-picker/native/story.tsx +26 -0
  256. package/registry/examples/meter/native/credits.d.ts +4 -0
  257. package/registry/examples/meter/native/credits.dark.png +0 -0
  258. package/registry/examples/meter/native/credits.js +15 -0
  259. package/registry/examples/meter/native/credits.light.png +0 -0
  260. package/registry/examples/meter/native/credits.tsx +12 -0
  261. package/registry/examples/meter/native/split-ring.d.ts +4 -0
  262. package/registry/examples/meter/native/split-ring.dark.png +0 -0
  263. package/registry/examples/meter/native/split-ring.js +24 -0
  264. package/registry/examples/meter/native/split-ring.light.png +0 -0
  265. package/registry/examples/meter/native/split-ring.tsx +19 -0
  266. package/registry/examples/number-ticker/native/balance.d.ts +4 -0
  267. package/registry/examples/number-ticker/native/balance.dark.png +0 -0
  268. package/registry/examples/number-ticker/native/balance.js +18 -0
  269. package/registry/examples/number-ticker/native/balance.light.png +0 -0
  270. package/registry/examples/number-ticker/native/balance.tsx +17 -0
  271. package/registry/examples/onboarding/native/first-launch.d.ts +4 -0
  272. package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
  273. package/registry/examples/onboarding/native/first-launch.js +23 -0
  274. package/registry/examples/onboarding/native/first-launch.light.png +0 -0
  275. package/registry/examples/onboarding/native/first-launch.tsx +19 -0
  276. package/registry/examples/otp-input/native/invalid.d.ts +4 -0
  277. package/registry/examples/otp-input/native/invalid.dark.png +0 -0
  278. package/registry/examples/otp-input/native/invalid.js +15 -0
  279. package/registry/examples/otp-input/native/invalid.light.png +0 -0
  280. package/registry/examples/otp-input/native/invalid.tsx +14 -0
  281. package/registry/examples/otp-input/native/verify.d.ts +4 -0
  282. package/registry/examples/otp-input/native/verify.dark.png +0 -0
  283. package/registry/examples/otp-input/native/verify.js +17 -0
  284. package/registry/examples/otp-input/native/verify.light.png +0 -0
  285. package/registry/examples/otp-input/native/verify.tsx +14 -0
  286. package/registry/examples/permission-prompt/native/blocked.d.ts +4 -0
  287. package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
  288. package/registry/examples/permission-prompt/native/blocked.js +25 -0
  289. package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
  290. package/registry/examples/permission-prompt/native/blocked.tsx +21 -0
  291. package/registry/examples/permission-prompt/native/camera.d.ts +4 -0
  292. package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
  293. package/registry/examples/permission-prompt/native/camera.js +25 -0
  294. package/registry/examples/permission-prompt/native/camera.light.png +0 -0
  295. package/registry/examples/permission-prompt/native/camera.tsx +21 -0
  296. package/registry/examples/pull-to-refresh/native/feed.d.ts +4 -0
  297. package/registry/examples/pull-to-refresh/native/feed.dark.png +0 -0
  298. package/registry/examples/pull-to-refresh/native/feed.js +14 -0
  299. package/registry/examples/pull-to-refresh/native/feed.light.png +0 -0
  300. package/registry/examples/pull-to-refresh/native/feed.tsx +19 -0
  301. package/registry/examples/radio-group/buttons.d.ts +4 -0
  302. package/registry/examples/radio-group/buttons.js +17 -0
  303. package/registry/examples/radio-group/buttons.tsx +21 -0
  304. package/registry/examples/radio-group/cards.js +1 -1
  305. package/registry/examples/radio-group/cards.tsx +2 -2
  306. package/registry/examples/radio-group/native/buttons.d.ts +4 -0
  307. package/registry/examples/radio-group/native/buttons.dark.png +0 -0
  308. package/registry/examples/radio-group/native/buttons.js +25 -0
  309. package/registry/examples/radio-group/native/buttons.light.png +0 -0
  310. package/registry/examples/radio-group/native/buttons.tsx +21 -0
  311. package/registry/examples/radio-group/native/cards.d.ts +4 -0
  312. package/registry/examples/radio-group/native/cards.dark.png +0 -0
  313. package/registry/examples/radio-group/native/cards.js +23 -0
  314. package/registry/examples/radio-group/native/cards.light.png +0 -0
  315. package/registry/examples/radio-group/native/cards.tsx +19 -0
  316. package/registry/examples/radio-group/native/list.d.ts +4 -0
  317. package/registry/examples/radio-group/native/list.dark.png +0 -0
  318. package/registry/examples/radio-group/native/list.js +24 -0
  319. package/registry/examples/radio-group/native/list.light.png +0 -0
  320. package/registry/examples/radio-group/native/list.tsx +20 -0
  321. package/registry/examples/radio-group/native/segmented.d.ts +4 -0
  322. package/registry/examples/radio-group/native/segmented.dark.png +0 -0
  323. package/registry/examples/radio-group/native/segmented.js +24 -0
  324. package/registry/examples/radio-group/native/segmented.light.png +0 -0
  325. package/registry/examples/radio-group/native/segmented.tsx +20 -0
  326. package/registry/examples/radio-group/segmented.d.ts +4 -0
  327. package/registry/examples/radio-group/segmented.js +15 -0
  328. package/registry/examples/radio-group/segmented.tsx +12 -0
  329. package/registry/examples/search-field/native/cancel.d.ts +4 -0
  330. package/registry/examples/search-field/native/cancel.dark.png +0 -0
  331. package/registry/examples/search-field/native/cancel.js +14 -0
  332. package/registry/examples/search-field/native/cancel.light.png +0 -0
  333. package/registry/examples/search-field/native/cancel.tsx +13 -0
  334. package/registry/examples/slider/floating.d.ts +4 -0
  335. package/registry/examples/slider/floating.js +11 -0
  336. package/registry/examples/slider/floating.tsx +12 -0
  337. package/registry/examples/slider/native/default.d.ts +4 -0
  338. package/registry/examples/slider/native/default.dark.png +0 -0
  339. package/registry/examples/slider/native/default.js +14 -0
  340. package/registry/examples/slider/native/default.light.png +0 -0
  341. package/registry/examples/slider/native/default.tsx +13 -0
  342. package/registry/examples/slider/native/range.d.ts +4 -0
  343. package/registry/examples/slider/native/range.dark.png +0 -0
  344. package/registry/examples/slider/native/range.js +12 -0
  345. package/registry/examples/slider/native/range.light.png +0 -0
  346. package/registry/examples/slider/native/range.tsx +11 -0
  347. package/registry/examples/slider/native/stepped.d.ts +4 -0
  348. package/registry/examples/slider/native/stepped.dark.png +0 -0
  349. package/registry/examples/slider/native/stepped.js +28 -0
  350. package/registry/examples/slider/native/stepped.light.png +0 -0
  351. package/registry/examples/slider/native/stepped.tsx +24 -0
  352. package/registry/examples/slider/native/vertical.d.ts +4 -0
  353. package/registry/examples/slider/native/vertical.dark.png +0 -0
  354. package/registry/examples/slider/native/vertical.js +16 -0
  355. package/registry/examples/slider/native/vertical.light.png +0 -0
  356. package/registry/examples/slider/native/vertical.tsx +13 -0
  357. package/registry/examples/slider/price-range.d.ts +4 -0
  358. package/registry/examples/slider/price-range.js +29 -0
  359. package/registry/examples/slider/price-range.tsx +27 -0
  360. package/registry/examples/slider/stepped.d.ts +4 -0
  361. package/registry/examples/slider/stepped.js +28 -0
  362. package/registry/examples/slider/stepped.tsx +24 -0
  363. package/registry/examples/slider/vertical.d.ts +4 -0
  364. package/registry/examples/slider/vertical.js +15 -0
  365. package/registry/examples/slider/vertical.tsx +14 -0
  366. package/registry/examples/stat/grid.d.ts +4 -0
  367. package/registry/examples/stat/grid.js +17 -0
  368. package/registry/examples/stat/grid.tsx +14 -0
  369. package/registry/examples/stepper/native/run.d.ts +4 -0
  370. package/registry/examples/stepper/native/run.dark.png +0 -0
  371. package/registry/examples/stepper/native/run.js +24 -0
  372. package/registry/examples/stepper/native/run.light.png +0 -0
  373. package/registry/examples/stepper/native/run.tsx +20 -0
  374. package/registry/examples/swipeable-row/native/conversation.d.ts +4 -0
  375. package/registry/examples/swipeable-row/native/conversation.dark.png +0 -0
  376. package/registry/examples/swipeable-row/native/conversation.js +30 -0
  377. package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
  378. package/registry/examples/swipeable-row/native/conversation.tsx +27 -0
  379. package/registry/examples/switch/native/default.d.ts +4 -0
  380. package/registry/examples/switch/native/default.dark.png +0 -0
  381. package/registry/examples/switch/native/default.js +16 -0
  382. package/registry/examples/switch/native/default.light.png +0 -0
  383. package/registry/examples/switch/native/default.tsx +13 -0
  384. package/registry/examples/switch/native/settings.d.ts +4 -0
  385. package/registry/examples/switch/native/settings.dark.png +0 -0
  386. package/registry/examples/switch/native/settings.js +20 -0
  387. package/registry/examples/switch/native/settings.light.png +0 -0
  388. package/registry/examples/switch/native/settings.tsx +17 -0
  389. package/registry/examples/tab-bar/native/main-sections.d.ts +4 -0
  390. package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
  391. package/registry/examples/tab-bar/native/main-sections.js +29 -0
  392. package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
  393. package/registry/examples/tab-bar/native/main-sections.tsx +30 -0
  394. package/registry/examples/tabs/native/sections.d.ts +4 -0
  395. package/registry/examples/tabs/native/sections.dark.png +0 -0
  396. package/registry/examples/tabs/native/sections.js +23 -0
  397. package/registry/examples/tabs/native/sections.light.png +0 -0
  398. package/registry/examples/tabs/native/sections.tsx +19 -0
  399. package/registry/examples/tabs/native/segmented.d.ts +4 -0
  400. package/registry/examples/tabs/native/segmented.dark.png +0 -0
  401. package/registry/examples/tabs/native/segmented.js +22 -0
  402. package/registry/examples/tabs/native/segmented.light.png +0 -0
  403. package/registry/examples/tabs/native/segmented.tsx +18 -0
  404. package/registry/examples/toast/native/snackbar.d.ts +4 -0
  405. package/registry/examples/toast/native/snackbar.dark.png +0 -0
  406. package/registry/examples/toast/native/snackbar.js +23 -0
  407. package/registry/examples/toast/native/snackbar.light.png +0 -0
  408. package/registry/examples/toast/native/snackbar.tsx +21 -0
  409. package/registry/examples/tree-view/docs.d.ts +4 -0
  410. package/registry/examples/tree-view/docs.js +24 -0
  411. package/registry/examples/tree-view/docs.tsx +22 -0
  412. package/registry/examples/tree-view/lazy.d.ts +4 -0
  413. package/registry/examples/tree-view/lazy.js +21 -0
  414. package/registry/examples/tree-view/lazy.tsx +19 -0
  415. package/registry/fab.json +122 -0
  416. package/registry/field.json +16 -4
  417. package/registry/file-upload.json +2 -2
  418. package/registry/filter-bar.json +1 -1
  419. package/registry/form.json +252 -44
  420. package/registry/gallery-page.json +1 -1
  421. package/registry/glow-card.json +1 -1
  422. package/registry/goal-gauge.json +1 -1
  423. package/registry/header.json +137 -0
  424. package/registry/how-it-works-page.json +1 -1
  425. package/registry/image-cropper.json +1 -1
  426. package/registry/image-viewer.json +107 -0
  427. package/registry/index.json +322 -44
  428. package/registry/iso.json +1 -1
  429. package/registry/kanban.json +253 -0
  430. package/registry/kbd.json +1 -1
  431. package/registry/landing-page.json +1 -1
  432. package/registry/landscape.json +1 -1
  433. package/registry/legal-page.json +1 -1
  434. package/registry/link-card.json +1 -1
  435. package/registry/list.json +367 -30
  436. package/registry/loader.json +157 -4
  437. package/registry/longform-page.json +1 -1
  438. package/registry/map.json +1368 -0
  439. package/registry/marketing-layout.json +1 -1
  440. package/registry/marquee.json +1 -1
  441. package/registry/mascot-quote.json +1 -1
  442. package/registry/mascot-state.json +1 -1
  443. package/registry/mascots.json +1 -1
  444. package/registry/media-capture.json +1 -1
  445. package/registry/media-picker.json +129 -0
  446. package/registry/meter.json +136 -4
  447. package/registry/nav-bar.json +1 -1
  448. package/registry/number-ticker.json +96 -4
  449. package/registry/onboarding.json +95 -0
  450. package/registry/otp-input.json +150 -0
  451. package/registry/page-header.json +1 -1
  452. package/registry/page-hero.json +1 -1
  453. package/registry/page.json +1 -1
  454. package/registry/pagination.json +1 -1
  455. package/registry/permission-prompt.json +172 -0
  456. package/registry/pointer-light.json +1 -1
  457. package/registry/popover.json +1 -1
  458. package/registry/pricing-page.json +1 -1
  459. package/registry/product-page.json +1 -1
  460. package/registry/profile-card.json +1 -1
  461. package/registry/progress.json +2 -2
  462. package/registry/promise-card.json +1 -1
  463. package/registry/pull-to-refresh.json +74 -0
  464. package/registry/radio-group.json +228 -16
  465. package/registry/scroll-stage.json +1 -1
  466. package/registry/search-field.json +30 -3
  467. package/registry/section-backdrop.json +1 -1
  468. package/registry/separator.json +1 -1
  469. package/registry/settings-layout.json +1 -1
  470. package/registry/skeleton.json +1 -1
  471. package/registry/slider.json +315 -14
  472. package/registry/slot.json +1 -1
  473. package/registry/spinner.json +1 -1
  474. package/registry/split-view.json +1 -1
  475. package/registry/stage-banner.json +1 -1
  476. package/registry/stat.json +68 -5
  477. package/registry/status-page.json +1 -1
  478. package/registry/stepper.json +75 -4
  479. package/registry/swipeable-row.json +124 -0
  480. package/registry/switch.json +116 -4
  481. package/registry/tab-bar.json +115 -0
  482. package/registry/tabs.json +96 -6
  483. package/registry/tag-input.json +1 -1
  484. package/registry/terminal-replay.json +1 -1
  485. package/registry/theme.json +8 -1
  486. package/registry/toast.json +17 -3
  487. package/registry/toc.json +1 -1
  488. package/registry/tooltip.json +1 -1
  489. package/registry/tree-view.json +291 -0
  490. package/registry/video-player.json +1 -1
  491. package/registry/video-trimmer.json +1 -1
  492. package/registry/virtual.json +1 -1
  493. package/skills/choice-controls/SKILL.md +39 -0
  494. package/skills/form/SKILL.md +3 -0
  495. package/skills/map/SKILL.md +35 -0
  496. package/dist/chunk-I5RVM5CW.js.map +0 -1
  497. package/dist/chunk-RUPRYJ45.js +0 -82
  498. package/dist/chunk-RUPRYJ45.js.map +0 -1
@@ -0,0 +1,291 @@
1
+ {
2
+ "name": "tree-view",
3
+ "type": "primitive",
4
+ "title": "Tree view",
5
+ "summary": "A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.",
6
+ "description": "A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.",
7
+ "status": "beta",
8
+ "category": "navigation",
9
+ "platforms": "web",
10
+ "whenToUse": [
11
+ "The documentation's sections (krizaka.com/docs).",
12
+ "A studio's datasets, folders of files."
13
+ ],
14
+ "whenNotToUse": [
15
+ {
16
+ "when": "For two levels or fewer: a list with headings reads better.",
17
+ "use": "list"
18
+ },
19
+ {
20
+ "when": "On a phone: drill down screen by screen with a list.",
21
+ "use": "list"
22
+ }
23
+ ],
24
+ "bestPractices": [
25
+ "Open the branch of the selected node at first (`defaultExpanded`).",
26
+ "Load big branches on demand (`hasChildren` + `onLoadChildren`)."
27
+ ],
28
+ "accessibility": {
29
+ "keyboard": [
30
+ {
31
+ "keys": "Arrow Down / Arrow Up",
32
+ "action": "Move to the next or previous visible node."
33
+ },
34
+ {
35
+ "keys": "Arrow Right",
36
+ "action": "Opens a closed branch, or moves to its first child."
37
+ },
38
+ {
39
+ "keys": "Arrow Left",
40
+ "action": "Closes an open branch, or moves to its parent."
41
+ },
42
+ {
43
+ "keys": "Home / End",
44
+ "action": "Move to the first or last visible node."
45
+ },
46
+ {
47
+ "keys": "Enter / Space",
48
+ "action": "Select the node (`onSelect`)."
49
+ },
50
+ {
51
+ "keys": "A letter",
52
+ "action": "Moves to the next node whose name starts with it."
53
+ }
54
+ ],
55
+ "notes": [
56
+ "`tree`, `treeitem` and `group` with level, position and size; a loading branch is busy.",
57
+ "Web only: a phone drills down with lists."
58
+ ]
59
+ },
60
+ "related": [
61
+ "list",
62
+ "nav-bar"
63
+ ],
64
+ "web": {
65
+ "entry": "@krizaka/ui/tree-view",
66
+ "import": "import { TreeView } from \"@krizaka/ui/tree-view\";",
67
+ "props": [
68
+ {
69
+ "component": "TreeView",
70
+ "description": "A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\nopens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.",
71
+ "props": [
72
+ {
73
+ "name": "aria-label",
74
+ "type": "string",
75
+ "default": null,
76
+ "description": "The tree's accessible name (“Documentation”).",
77
+ "required": true
78
+ },
79
+ {
80
+ "name": "nodes",
81
+ "type": "readonly TreeNode[]",
82
+ "default": null,
83
+ "description": "The roots.",
84
+ "required": true
85
+ },
86
+ {
87
+ "name": "className",
88
+ "type": "string",
89
+ "default": null,
90
+ "description": "Classes merged on the tree.",
91
+ "required": false
92
+ },
93
+ {
94
+ "name": "defaultExpanded",
95
+ "type": "readonly string[]",
96
+ "default": "[]",
97
+ "description": "The ids open at first, uncontrolled.",
98
+ "required": false
99
+ },
100
+ {
101
+ "name": "defaultSelected",
102
+ "type": "string | null",
103
+ "default": "null",
104
+ "description": "The selected node at first, uncontrolled.",
105
+ "required": false
106
+ },
107
+ {
108
+ "name": "expanded",
109
+ "type": "readonly string[]",
110
+ "default": null,
111
+ "description": "The ids of the open branches (controlled).",
112
+ "required": false
113
+ },
114
+ {
115
+ "name": "loadingLabel",
116
+ "type": "string",
117
+ "default": "Loading",
118
+ "description": "The words of a branch that is loading (“Loading”).",
119
+ "required": false
120
+ },
121
+ {
122
+ "name": "onExpandedChange",
123
+ "type": "((expanded: string[]) => void)",
124
+ "default": null,
125
+ "description": "Called with the open branches.",
126
+ "required": false
127
+ },
128
+ {
129
+ "name": "onLoadChildren",
130
+ "type": "((node: TreeNode) => void)",
131
+ "default": null,
132
+ "description": "Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`.",
133
+ "required": false
134
+ },
135
+ {
136
+ "name": "onSelect",
137
+ "type": "((node: TreeNode) => void)",
138
+ "default": null,
139
+ "description": "Called when a node is chosen (click, Enter or Space): navigate, open the file.",
140
+ "required": false
141
+ },
142
+ {
143
+ "name": "selected",
144
+ "type": "string | null",
145
+ "default": null,
146
+ "description": "The selected node (controlled).",
147
+ "required": false
148
+ }
149
+ ]
150
+ }
151
+ ],
152
+ "examples": [
153
+ {
154
+ "name": "docs",
155
+ "title": "Documentation",
156
+ "description": "Products, sections and pages, the current page selected.",
157
+ "path": "examples/tree-view/docs.tsx",
158
+ "module": "@krizaka/ui/registry/examples/tree-view/docs",
159
+ "code": "\"use client\";\n\nimport { TreeView } from \"@krizaka/ui/tree-view\";\n\nconst nodes = [\n {\n id: \"orazaka\",\n label: \"Orazaka\",\n children: [\n { id: \"getting-started\", label: \"Getting started\" },\n { id: \"studios\", label: \"Studios\", meta: \"12\", children: [{ id: \"dubbing\", label: \"Dubbing\" }, { id: \"transcript\", label: \"Transcript\" }, { id: \"clips\", label: \"Clips\" }] },\n { id: \"api\", label: \"API reference\" },\n ],\n },\n { id: \"orochia\", label: \"Orochia\", children: [{ id: \"auctions\", label: \"Auctions\" }, { id: \"challenges\", label: \"Challenges\" }] },\n { id: \"ui\", label: \"Krizaka UI\", children: [{ id: \"components\", label: \"Components\" }] },\n];\n\n// The documentation's sections: one tab stop, the arrows walk and open, a letter jumps.\nexport default function TreeViewDocs() {\n return <TreeView aria-label=\"Documentation\" nodes={nodes} defaultExpanded={[\"orazaka\", \"studios\"]} defaultSelected=\"dubbing\" className=\"max-w-xs\" />;\n}\n"
160
+ },
161
+ {
162
+ "name": "lazy",
163
+ "title": "Loaded on demand",
164
+ "description": "A branch fetches its files when it opens.",
165
+ "path": "examples/tree-view/lazy.tsx",
166
+ "module": "@krizaka/ui/registry/examples/tree-view/lazy",
167
+ "code": "\"use client\";\n\nimport { type TreeNode, TreeView } from \"@krizaka/ui/tree-view\";\nimport { useState } from \"react\";\n\n// A studio's datasets: a branch loads its files when it opens (here after 600 ms).\nexport default function TreeViewLazy() {\n const [nodes, setNodes] = useState<TreeNode[]>([\n { id: \"voices\", label: \"Voices\", hasChildren: true, meta: \"3\" },\n { id: \"glossaries\", label: \"Glossaries\", hasChildren: true, meta: \"2\" },\n { id: \"readme\", label: \"README.md\" },\n ]);\n const load = (node: TreeNode) =>\n setTimeout(() => {\n const files = Array.from({ length: Number(node.meta) }, (_, i) => ({ id: `${node.id}-${i}`, label: `${node.label.toLowerCase()}-${i + 1}.json` }));\n setNodes((all) => all.map((n) => (n.id === node.id ? { ...n, children: files } : n)));\n }, 600);\n return <TreeView aria-label=\"Datasets\" nodes={nodes} onLoadChildren={load} loadingLabel=\"Loading the files\" className=\"max-w-xs\" />;\n}\n"
168
+ }
169
+ ]
170
+ },
171
+ "native": null,
172
+ "files": [
173
+ {
174
+ "path": "glyphs.tsx",
175
+ "content": "// The small line glyphs the data and media primitives draw (play, volume, search, chevrons…): decorative, 24-unit\n// box, `currentColor`, sized by the caller's class. Shared by the entries that need them; never exported on its own —\n// a product draws its own icons with @krizaka/icons.\nimport type * as React from \"react\";\n\ntype GlyphProps = { className?: string };\n\nfunction Glyph({ className = \"h-4 w-4\", fill, children }: GlyphProps & { fill?: boolean; children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n className={className}\n fill={fill ? \"currentColor\" : \"none\"}\n stroke={fill ? \"none\" : \"currentColor\"}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n focusable=\"false\"\n >\n {children}\n </svg>\n );\n}\n\nexport const PlayGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <path d=\"M8 5.5v13a1 1 0 0 0 1.5.86l10.4-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5Z\" />\n </Glyph>\n);\nexport const PauseGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n </Glyph>\n);\nexport const VolumeGlyph = ({ muted, ...p }: GlyphProps & { muted?: boolean }) => (\n <Glyph {...p}>\n <path d=\"M11 5 6 9H3v6h3l5 4V5Z\" />\n {muted ? <path d=\"m22 9-6 6m0-6 6 6\" /> : <path d=\"M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13\" />}\n </Glyph>\n);\nexport const FullscreenGlyph = ({ exit, ...p }: GlyphProps & { exit?: boolean }) => (\n <Glyph {...p}>\n {exit ? <path d=\"M9 4v5H4m11-5v5h5M9 20v-5H4m11 5v-5h5\" /> : <path d=\"M4 9V4h5m6 0h5v5M4 15v5h5m11-5v5h-5\" />}\n </Glyph>\n);\nexport const CaptionsGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"M10 10.5a2 2 0 1 0 0 3M17 10.5a2 2 0 1 0 0 3\" />\n </Glyph>\n);\nexport const PipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <rect x=\"12\" y=\"12\" width=\"6\" height=\"4\" rx=\"1\" />\n </Glyph>\n);\nexport const SearchGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </Glyph>\n);\nexport const CloseGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </Glyph>\n);\nexport const ChevronGlyph = ({ direction = \"down\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" | \"up\" | \"down\" }) => (\n <Glyph {...p}>\n <path d={{ left: \"m15 6-6 6 6 6\", right: \"m9 6 6 6-6 6\", up: \"m6 15 6-6 6 6\", down: \"m6 9 6 6 6-6\" }[direction]} />\n </Glyph>\n);\nexport const CheckGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Glyph>\n);\nexport const PlusGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 5v14M5 12h14\" />\n </Glyph>\n);\nexport const CalendarGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\" />\n <path d=\"M3 10h18M8 3v4M16 3v4\" />\n </Glyph>\n);\nexport const UploadGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 16V4m0 0L7 9m5-5 5 5\" />\n <path d=\"M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\" />\n </Glyph>\n);\nexport const FileGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8l-5-5Z\" />\n <path d=\"M14 3v5h5\" />\n </Glyph>\n);\nexport const CameraGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 8h3l2-3h6l2 3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1Z\" />\n <circle cx=\"12\" cy=\"13.5\" r=\"3.5\" />\n </Glyph>\n);\nexport const FlipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 0 1 14-5.3M20 12a8 8 0 0 1-14 5.3\" />\n <path d=\"M18 3v4h-4M6 21v-4h4\" />\n </Glyph>\n);\nexport const RetryGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 1 0 2.3-5.7L4 8.5\" />\n <path d=\"M4 4v4.5h4.5\" />\n </Glyph>\n);\nexport const SortGlyph = ({ direction, ...p }: GlyphProps & { direction?: \"ascending\" | \"descending\" }) => (\n <Glyph {...p}>\n {direction === \"ascending\" ? <path d=\"m7 14 5-5 5 5\" /> : direction === \"descending\" ? <path d=\"m7 10 5 5 5-5\" /> : <path d=\"m8 9 4-4 4 4M8 15l4 4 4-4\" />}\n </Glyph>\n);\nexport const ArrowGlyph = ({ direction = \"right\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" }) => (\n <Glyph {...p}>\n <path d={direction === \"left\" ? \"M19 12H5m0 0 6-6m-6 6 6 6\" : \"M5 12h14m0 0-6-6m6 6-6 6\"} />\n </Glyph>\n);\nexport const ExternalGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 4h6v6M20 4l-9 9\" />\n <path d=\"M18 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4\" />\n </Glyph>\n);\nexport const WarningGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 4 2.5 20h19L12 4Z\" />\n <path d=\"M12 10v4M12 17.2v.1\" />\n </Glyph>\n);\nexport const CopyGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n <path d=\"M15 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3\" />\n </Glyph>\n);\n"
176
+ },
177
+ {
178
+ "path": "media.ts",
179
+ "content": "// Shared by the data and media primitives (client): the clock format, the reduced-motion preference, the\n// in-view observer, a debounced callback. Never an entry of its own.\nimport * as React from \"react\";\n\n/** Seconds as a clock: `75` → `1:15`, `3725` → `1:02:05`. Negative or unknown values read `0:00`. */\nexport function formatClock(seconds: number): string {\n const s = Number.isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0;\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const rest = String(s % 60).padStart(2, \"0\");\n return h > 0 ? `${h}:${String(m).padStart(2, \"0\")}:${rest}` : `${m}:${rest}`;\n}\n\n/** Clamps `value` between `min` and `max`. */\nexport const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst REDUCE = \"(prefers-reduced-motion: reduce)\";\nconst subscribeReduce = (notify: () => void) => {\n if (typeof window === \"undefined\" || !window.matchMedia) return () => undefined;\n const query = window.matchMedia(REDUCE);\n query.addEventListener?.(\"change\", notify);\n return () => query.removeEventListener?.(\"change\", notify);\n};\n\n/** `true` when the person asked for less motion (`prefers-reduced-motion: reduce`); follows a change of the setting. */\nexport function usePrefersReducedMotion(): boolean {\n return React.useSyncExternalStore(\n subscribeReduce,\n () => (typeof window !== \"undefined\" && window.matchMedia ? window.matchMedia(REDUCE).matches : false),\n () => false,\n );\n}\n\n/** The latest value of a callback, for an effect or an event that must not re-subscribe when it changes. */\nexport function useLatest<T>(value: T) {\n const ref = React.useRef(value);\n React.useLayoutEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n\n/** Calls `onChange(visible)` when at least `threshold` of the element enters or leaves the viewport. */\nexport function useInView(ref: React.RefObject<Element | null>, onChange: (visible: boolean) => void, enabled = true, threshold = 0.25) {\n const latest = useLatest(onChange);\n React.useEffect(() => {\n const element = ref.current;\n if (!enabled || !element || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(([entry]) => entry && latest.current(entry.isIntersecting), { threshold });\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref, enabled, threshold, latest]);\n}\n\n/** A stable function that runs `callback` once `delay` ms have passed without a new call; `cancel()` drops the pending one. */\nexport function useDebouncedCallback<A extends unknown[]>(callback: (...args: A) => void, delay: number) {\n const latest = useLatest(callback);\n const [debounced] = React.useState(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let wait = delay;\n const run = (...args: A) => {\n clearTimeout(timer);\n if (wait <= 0) latest.current(...args);\n else timer = setTimeout(() => latest.current(...args), wait);\n };\n return Object.assign(run, {\n cancel: () => clearTimeout(timer),\n setDelay: (next: number) => {\n wait = next;\n },\n });\n });\n React.useEffect(() => debounced.setDelay(delay), [debounced, delay]);\n React.useEffect(() => () => debounced.cancel(), [debounced]);\n return debounced;\n}\n\n/** A value controlled by a prop when it is given, held inside otherwise; `set` calls `onChange` either way. */\nexport function useControllable<T>(value: T | undefined, defaultValue: T, onChange?: (next: T) => void) {\n const [inner, setInner] = React.useState(defaultValue);\n const controlled = value !== undefined;\n const current = controlled ? value : inner;\n const set = React.useCallback(\n (next: T) => {\n if (!controlled) setInner(next);\n onChange?.(next);\n },\n [controlled, onChange],\n );\n return [current, set] as const;\n}\n\n/** Starts a media element without an unhandled rejection (autoplay refused, the source replaced meanwhile). */\nexport function playSafely(media: HTMLMediaElement | null | undefined) {\n try {\n const started = media?.play() as Promise<void> | undefined;\n started?.catch?.(() => undefined);\n } catch {\n // Not playable here (no media support): the controls stay as they are.\n }\n}\n"
180
+ },
181
+ {
182
+ "path": "meta.ts",
183
+ "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
184
+ },
185
+ {
186
+ "path": "tree-view/index.ts",
187
+ "content": "/** @krizaka/ui/tree-view — `TreeView`: a hierarchy the keyboard walks (the ARIA tree), branches loaded on demand. */\nexport { type TreeNode, TreeView, treeView, type TreeViewProps } from \"./tree-view\";\n"
188
+ },
189
+ {
190
+ "path": "tree-view/meta.ts",
191
+ "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Tree view\",\n summary: \"A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.\",\n status: \"beta\",\n category: \"navigation\",\n platforms: \"web\",\n whenToUse: [\"The documentation's sections (krizaka.com/docs).\", \"A studio's datasets, folders of files.\"],\n whenNotToUse: [\n { when: \"For two levels or fewer: a list with headings reads better.\", use: \"list\" },\n { when: \"On a phone: drill down screen by screen with a list.\", use: \"list\" },\n ],\n bestPractices: [\"Open the branch of the selected node at first (`defaultExpanded`).\", \"Load big branches on demand (`hasChildren` + `onLoadChildren`).\"],\n accessibility: {\n keyboard: [\n { keys: \"Arrow Down / Arrow Up\", action: \"Move to the next or previous visible node.\" },\n { keys: \"Arrow Right\", action: \"Opens a closed branch, or moves to its first child.\" },\n { keys: \"Arrow Left\", action: \"Closes an open branch, or moves to its parent.\" },\n { keys: \"Home / End\", action: \"Move to the first or last visible node.\" },\n { keys: \"Enter / Space\", action: \"Select the node (`onSelect`).\" },\n { keys: \"A letter\", action: \"Moves to the next node whose name starts with it.\" },\n ],\n notes: [\"`tree`, `treeitem` and `group` with level, position and size; a loading branch is busy.\", \"Web only: a phone drills down with lists.\"],\n },\n related: [\"list\", \"nav-bar\"],\n web: {\n imports: [\"TreeView\"],\n examples: [\n { name: \"docs\", title: \"Documentation\", description: \"Products, sections and pages, the current page selected.\" },\n { name: \"lazy\", title: \"Loaded on demand\", description: \"A branch fetches its files when it opens.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
192
+ },
193
+ {
194
+ "path": "tree-view/tree-view.tsx",
195
+ "content": "// Client (expansion, selection, the roving focus). A hierarchy the keyboard walks — the ARIA tree pattern: one tab\n// stop, the arrows move and open, Home/End, typing a letter jumps; children loaded on demand when a branch opens.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronGlyph } from \"../glyphs\";\nimport { useControllable } from \"../media\";\n\nexport const treeView = tv({\n slots: {\n root: \"m-0 list-none p-0 text-sm\",\n group: \"m-0 list-none p-0\",\n row:\n \"flex min-h-8 cursor-pointer select-none items-center gap-1.5 rounded-md pr-2 text-fg outline-hidden \" +\n \"hover:bg-surface-2 data-[selected]:bg-accent-soft data-[selected]:font-semibold data-[disabled]:cursor-default data-[disabled]:opacity-50\",\n toggle: \"flex h-5 w-5 shrink-0 items-center justify-center text-fg-secondary [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:transition-transform motion-reduce:[&>svg]:transition-none\",\n icon: \"flex shrink-0 items-center text-fg-secondary [&>svg]:h-4 [&>svg]:w-4\",\n label: \"min-w-0 flex-1 truncate\",\n meta: \"shrink-0 text-xs tabular-nums text-fg-secondary\",\n },\n});\n\nexport type TreeNode = {\n /** A stable id. */\n id: string;\n /** Its name — passed translated. */\n label: string;\n /** A decorative icon before the name. */\n icon?: React.ReactNode;\n /** A detail after the name (a count, a size). */\n meta?: React.ReactNode;\n /** Its children; `undefined` for a leaf. With `hasChildren`, they load when it opens (`onLoadChildren`). */\n children?: readonly TreeNode[];\n /** A branch whose children are not loaded yet. */\n hasChildren?: boolean;\n /** Cannot be selected. */\n disabled?: boolean;\n};\n\nexport type TreeViewProps = {\n /** The roots. */\n nodes: readonly TreeNode[];\n /** The tree's accessible name (“Documentation”). */\n \"aria-label\": string;\n /** The ids of the open branches (controlled). */\n expanded?: readonly string[];\n /** The ids open at first, uncontrolled. */\n defaultExpanded?: readonly string[];\n /** Called with the open branches. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The selected node (controlled). */\n selected?: string | null;\n /** The selected node at first, uncontrolled. */\n defaultSelected?: string | null;\n /** Called when a node is chosen (click, Enter or Space): navigate, open the file. */\n onSelect?: (node: TreeNode) => void;\n /** Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`. */\n onLoadChildren?: (node: TreeNode) => void;\n /** The words of a branch that is loading (“Loading”). */\n loadingLabel?: string;\n /** Classes merged on the tree. */\n className?: string;\n};\n\ntype Flat = { node: TreeNode; level: number; parent: string | null; posinset: number; setsize: number };\n\nconst isBranch = (node: TreeNode) => Boolean(node.children?.length || node.hasChildren);\n\nfunction flatten(nodes: readonly TreeNode[], open: Set<string>, level = 1, parent: string | null = null, out: Flat[] = []): Flat[] {\n nodes.forEach((node, i) => {\n out.push({ node, level, parent, posinset: i + 1, setsize: nodes.length });\n if (open.has(node.id) && node.children) flatten(node.children, open, level + 1, node.id, out);\n });\n return out;\n}\n\n/**\n * A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\n * opens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.\n */\nexport function TreeView({\n nodes,\n \"aria-label\": label,\n expanded: expandedProp,\n defaultExpanded = [],\n onExpandedChange,\n selected: selectedProp,\n defaultSelected = null,\n onSelect,\n onLoadChildren,\n loadingLabel = \"Loading\",\n className,\n}: TreeViewProps) {\n const s = treeView();\n const uid = React.useId();\n const [expanded, setExpanded] = useControllable<readonly string[]>(expandedProp, defaultExpanded, onExpandedChange as (next: readonly string[]) => void);\n const [selected, setSelected] = useControllable<string | null>(selectedProp, defaultSelected);\n const open = new Set(expanded);\n const rows = flatten(nodes, open);\n const [active, setActive] = React.useState<string | null>(null);\n const focusId = active && rows.some((r) => r.node.id === active) ? active : (selected ?? rows[0]?.node.id ?? null);\n const refs = React.useRef(new Map<string, HTMLDivElement>());\n const move = (id: string | undefined) => {\n if (!id) return;\n setActive(id);\n refs.current.get(id)?.focus();\n };\n const toggle = (node: TreeNode, to = !open.has(node.id)) => {\n if (!isBranch(node)) return;\n if (to && node.hasChildren && !node.children) onLoadChildren?.(node);\n setExpanded(to ? [...expanded, node.id] : expanded.filter((id) => id !== node.id));\n };\n const choose = (node: TreeNode) => {\n if (node.disabled) return;\n setSelected(node.id);\n onSelect?.(node);\n };\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n const row = rows[i]!;\n const { node } = row;\n const keys: Record<string, () => void> = {\n ArrowDown: () => move(rows[i + 1]?.node.id),\n ArrowUp: () => move(rows[i - 1]?.node.id),\n Home: () => move(rows[0]?.node.id),\n End: () => move(rows[rows.length - 1]?.node.id),\n ArrowRight: () => (isBranch(node) && !open.has(node.id) ? toggle(node, true) : isBranch(node) ? move(rows[i + 1]?.node.id) : undefined),\n ArrowLeft: () => (open.has(node.id) ? toggle(node, false) : move(row.parent ?? undefined)),\n Enter: () => choose(node),\n \" \": () => choose(node),\n };\n const run = keys[event.key];\n if (run) {\n event.preventDefault();\n run();\n return;\n }\n if (event.key.length === 1 && /\\S/.test(event.key)) {\n const letter = event.key.toLowerCase();\n const next = [...rows.slice(i + 1), ...rows.slice(0, i)].find((r) => r.node.label.toLowerCase().startsWith(letter));\n move(next?.node.id);\n }\n };\n\n const render = (list: readonly TreeNode[], level: number): React.ReactNode =>\n list.map((node) => {\n const i = rows.findIndex((r) => r.node.id === node.id);\n const row = rows[i]!;\n const branch = isBranch(node);\n const isOpen = open.has(node.id);\n const loading = isOpen && node.hasChildren && !node.children;\n return (\n // The row is the treeitem (its name is its own words, never its children's); the group of children hangs\n // from it with aria-owns, in the `li` that holds both.\n <li key={node.id} role=\"none\">\n <div\n ref={(el) => {\n if (el) refs.current.set(node.id, el);\n else refs.current.delete(node.id);\n }}\n role=\"treeitem\"\n aria-level={level}\n aria-posinset={row.posinset}\n aria-setsize={row.setsize}\n aria-expanded={branch ? isOpen : undefined}\n aria-selected={selected === node.id}\n aria-disabled={node.disabled || undefined}\n aria-busy={loading || undefined}\n aria-owns={branch && isOpen ? `${uid}-${node.id}-group` : undefined}\n tabIndex={node.id === focusId ? 0 : -1}\n onKeyDown={(e) => {\n if (e.target === e.currentTarget) onKeyDown(e, i);\n }}\n onFocus={(e) => {\n if (e.target === e.currentTarget) setActive(node.id);\n }}\n className={s.row({ className: \"outline-hidden focus-visible:ring-2 focus-visible:ring-ring\" })}\n data-selected={selected === node.id || undefined}\n data-disabled={node.disabled || undefined}\n style={{ paddingLeft: `${(level - 1) * 1.25 + 0.25}rem` }}\n onClick={() => {\n if (branch) toggle(node);\n choose(node);\n move(node.id);\n }}\n >\n <span className={s.toggle()} aria-hidden>\n {branch ? <ChevronGlyph direction={isOpen ? \"down\" : \"right\"} /> : null}\n </span>\n {node.icon ? <span className={s.icon()} aria-hidden>{node.icon}</span> : null}\n <span className={s.label()}>{node.label}</span>\n {node.meta ? <span className={s.meta()}>{node.meta}</span> : null}\n </div>\n {branch && isOpen ? (\n <ul role=\"group\" id={`${uid}-${node.id}-group`} className={s.group()}>\n {loading ? (\n <li role=\"none\" className=\"py-1 text-xs text-fg-secondary\" style={{ paddingLeft: `${level * 1.25 + 1.75}rem` }}>\n {loadingLabel}\n </li>\n ) : (\n render(node.children ?? [], level + 1)\n )}\n </ul>\n ) : null}\n </li>\n );\n });\n\n return (\n <ul role=\"tree\" aria-label={label} className={s.root({ className })}>\n {render(nodes, 1)}\n </ul>\n );\n}\n"
196
+ }
197
+ ],
198
+ "dependencies": [
199
+ "tailwind-variants@^3.3.1"
200
+ ],
201
+ "registryDependencies": [],
202
+ "demo": {
203
+ "path": "examples/tree-view/docs.tsx",
204
+ "content": "\"use client\";\n\nimport { TreeView } from \"@krizaka/ui/tree-view\";\n\nconst nodes = [\n {\n id: \"orazaka\",\n label: \"Orazaka\",\n children: [\n { id: \"getting-started\", label: \"Getting started\" },\n { id: \"studios\", label: \"Studios\", meta: \"12\", children: [{ id: \"dubbing\", label: \"Dubbing\" }, { id: \"transcript\", label: \"Transcript\" }, { id: \"clips\", label: \"Clips\" }] },\n { id: \"api\", label: \"API reference\" },\n ],\n },\n { id: \"orochia\", label: \"Orochia\", children: [{ id: \"auctions\", label: \"Auctions\" }, { id: \"challenges\", label: \"Challenges\" }] },\n { id: \"ui\", label: \"Krizaka UI\", children: [{ id: \"components\", label: \"Components\" }] },\n];\n\n// The documentation's sections: one tab stop, the arrows walk and open, a letter jumps.\nexport default function TreeViewDocs() {\n return <TreeView aria-label=\"Documentation\" nodes={nodes} defaultExpanded={[\"orazaka\", \"studios\"]} defaultSelected=\"dubbing\" className=\"max-w-xs\" />;\n}\n"
205
+ },
206
+ "props": [
207
+ {
208
+ "component": "TreeView",
209
+ "description": "A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\nopens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.",
210
+ "props": [
211
+ {
212
+ "name": "aria-label",
213
+ "type": "string",
214
+ "default": null,
215
+ "description": "The tree's accessible name (“Documentation”).",
216
+ "required": true
217
+ },
218
+ {
219
+ "name": "nodes",
220
+ "type": "readonly TreeNode[]",
221
+ "default": null,
222
+ "description": "The roots.",
223
+ "required": true
224
+ },
225
+ {
226
+ "name": "className",
227
+ "type": "string",
228
+ "default": null,
229
+ "description": "Classes merged on the tree.",
230
+ "required": false
231
+ },
232
+ {
233
+ "name": "defaultExpanded",
234
+ "type": "readonly string[]",
235
+ "default": "[]",
236
+ "description": "The ids open at first, uncontrolled.",
237
+ "required": false
238
+ },
239
+ {
240
+ "name": "defaultSelected",
241
+ "type": "string | null",
242
+ "default": "null",
243
+ "description": "The selected node at first, uncontrolled.",
244
+ "required": false
245
+ },
246
+ {
247
+ "name": "expanded",
248
+ "type": "readonly string[]",
249
+ "default": null,
250
+ "description": "The ids of the open branches (controlled).",
251
+ "required": false
252
+ },
253
+ {
254
+ "name": "loadingLabel",
255
+ "type": "string",
256
+ "default": "Loading",
257
+ "description": "The words of a branch that is loading (“Loading”).",
258
+ "required": false
259
+ },
260
+ {
261
+ "name": "onExpandedChange",
262
+ "type": "((expanded: string[]) => void)",
263
+ "default": null,
264
+ "description": "Called with the open branches.",
265
+ "required": false
266
+ },
267
+ {
268
+ "name": "onLoadChildren",
269
+ "type": "((node: TreeNode) => void)",
270
+ "default": null,
271
+ "description": "Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`.",
272
+ "required": false
273
+ },
274
+ {
275
+ "name": "onSelect",
276
+ "type": "((node: TreeNode) => void)",
277
+ "default": null,
278
+ "description": "Called when a node is chosen (click, Enter or Space): navigate, open the file.",
279
+ "required": false
280
+ },
281
+ {
282
+ "name": "selected",
283
+ "type": "string | null",
284
+ "default": null,
285
+ "description": "The selected node (controlled).",
286
+ "required": false
287
+ }
288
+ ]
289
+ }
290
+ ]
291
+ }
@@ -408,7 +408,7 @@
408
408
  },
409
409
  {
410
410
  "path": "meta.ts",
411
- "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
411
+ "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
412
412
  },
413
413
  {
414
414
  "path": "video-player/index.ts",
@@ -225,7 +225,7 @@
225
225
  },
226
226
  {
227
227
  "path": "meta.ts",
228
- "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
228
+ "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
229
229
  },
230
230
  {
231
231
  "path": "video-trimmer/index.ts",
@@ -318,7 +318,7 @@
318
318
  },
319
319
  {
320
320
  "path": "meta.ts",
321
- "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
321
+ "content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
322
322
  },
323
323
  {
324
324
  "path": "virtual/index.ts",
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: krizaka-choice-controls
3
+ description: Choices and settings in a Krizaka app (Next.js or Expo) with @krizaka/ui — RadioGroup (dots, cards, tactile keys that press in, segmented), Slider (range, steps and marks, floating value, brand gradient, vertical), Switch, and on React Native Select / Combobox in a Sheet, with haptics through the ThemeProvider. Use it instead of React Native's Switch, a picker module, a hand-made segmented control or a slider library.
4
+ ---
5
+
6
+ # RadioGroup · Slider · Switch · Select · Combobox · Sheet
7
+
8
+ ## Rules
9
+
10
+ 1. Pick by the choice:
11
+ - two to five options seen at once → `RadioGroup` — `list` (settings), `cards` (an amount, a plan: a line under
12
+ each), `buttons` (a size, a tip, a level: tactile keys), `segmented` (two to four short words on one line);
13
+ - many options → web `Select` of `@krizaka/ui/field` (the platform's menu) or `Combobox` (searched); native `Select`
14
+ / `Combobox` (a field that opens a `Sheet`);
15
+ - a value by feel within bounds → `Slider` (`ticks` when the steps are few, `marks` to name the ends,
16
+ `floatingValue` while touched, `orientation="vertical"` for faders); an exact number → a text field;
17
+ - on / off, applied at once → `Switch` (native: `showLabel` + `description` makes the settings row).
18
+ 2. Never React Native's `Switch`, `@react-native-community/slider` or a picker module: the platform's controls are
19
+ drawn by the theme, the same on iOS and Android, and wear the product's accent.
20
+ 3. A segmented control that **switches views** is `Tabs variant="segmented"` (web) / `Segmented` (native); one that is a
21
+ **form's value** is `RadioGroup variant="segmented"`.
22
+ 4. Haptics: `<ThemeProvider haptics={(k) => k === "selection" ? Haptics.selectionAsync() : Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}>`
23
+ once at the root (expo-haptics). Wheels, slider steps, radios and switches play `selection`; a tactile key `impact`.
24
+ 5. Words are props (`label`, `thumbLabels`, `formatValue`, `hint`, `labels`), passed translated. In a form, use the
25
+ form's fields (`form.RadioGroup variant=…`, `form.Slider`, `form.Switch`, `form.Select`, `form.Combobox`).
26
+
27
+ ## Recipes
28
+
29
+ ```tsx
30
+ <RadioGroup.Root label={t("tip")} variant="buttons" value={tip} onValueChange={setTip}>
31
+ {TIPS.map((p) => <RadioGroup.Button key={p} value={p} hint={formatMoney(total * p / 100)}>{`${p} %`}</RadioGroup.Button>)}
32
+ </RadioGroup.Root>
33
+ <Slider<[number, number]> label={t("price")} thumbLabels={[t("min"), t("max")]} value={range} onValueChange={setRange}
34
+ max={250} step={10} floatingValue marks={[{ value: 0, label: "$0" }, { value: 250, label: "$250+" }]} />
35
+ // React Native
36
+ <Switch label={t("push")} description={t("push.hint")} showLabel checked={push} onCheckedChange={setPush} />
37
+ <Select label={t("language")} options={LANGUAGES} value={lang} onValueChange={setLang} />
38
+ <Combobox label={t("city")} onSearch={(q, signal) => searchCities(q, signal)} value={city} onValueChange={setCity} />
39
+ ```
@@ -40,5 +40,8 @@ const form = signUp.useForm({ i18n: { t }, codeFields: { USERNAME_RESERVED: "use
40
40
  - Amounts: `form.Money name="amount" currency="EUR"` stores integer cents (`z.number().int()`).
41
41
  - Lists: `<form.FieldArray name="links">{(a) => a.items.map((_, i) => <form.TextField name={`links[${i}].url`} … />)}</form.FieldArray>`.
42
42
  - Conditional parts: `<form.Watch name="audience">{(v) => v === "subscribers" ? <form.Money name="price" … /> : null}</form.Watch>`.
43
+ - Controls (DS5): `form.RadioGroup variant="buttons" | "segmented" | "cards"`, `form.DateField entry="wheel" max={latestBirthDate(18)}`,
44
+ `form.Slider ticks marks={…}` (the value floats while touched). Native: `DateField` is wheels by default, `Select` /
45
+ `Combobox` open a sheet, `Switch` is a settings row; pass `haptics` to the native `ThemeProvider` for the haptics.
43
46
  - Native: `<form.Form scroll>` makes the form the screen's scrolling content above the keyboard; the return key walks the
44
47
  text fields and the last one sends; `<form.Submit label=… brand="orochia" />` turns the product's mark while sending.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: krizaka-map
3
+ description: Maps in a Krizaka app (Next.js or Expo) with @krizaka/ui/map and @krizaka/ui/native/map — MapLibre (open source) over Protomaps PMTiles on the Krizaka CDN, no API key and no metered service, the style generated from the tokens (dark/light, the product's accent): Map, Marker, Cluster, UserPosition, RadiusCircle, LocationPicker (distance chip, Near me), StaticMap (fallback), mapStyle, distanceMeters. Use it instead of Mapbox, Google Maps, Leaflet with raster tiles or react-native-maps.
4
+ ---
5
+
6
+ # @krizaka/ui/map · @krizaka/ui/native/map
7
+
8
+ ## Rules
9
+
10
+ 1. Never Mapbox or Google Maps (keys, per-view bills): MapLibre + our PMTiles. Install the engine only in the app that
11
+ shows a map: web `maplibre-gl` (≥ 6), Expo `@maplibre/maplibre-react-native` (≥ 11, with its config plugin and the
12
+ location usage strings). `pmtiles` and `@protomaps/basemaps` come with `@krizaka/ui`.
13
+ 2. Every `Map` has a `label`, every `Marker` / `Cluster` point a `label`: they are the text alternative (a list of places
14
+ on the web, the map's name on native). Give the web `Map` a `fallback` — a `StaticMap` with the same centre and places.
15
+ 3. Pass the product: `brand="orochia"` paints the accent (markers, the water's tint); the scheme follows the page
16
+ (`html.light`) or the native theme.
17
+ 4. Ask for the position only when the person presses Near me (`LocationPicker`); never on load. Every answer has its words
18
+ (`labels.denied`, `labels.unavailable`), passed translated.
19
+ 5. Details of a place: a panel on the web, a `Sheet` (`@krizaka/ui/native`) on a phone, opened from `Marker onPress`.
20
+ 6. Tiles: the defaults are the world (zoom 0–6) and Montréal–Québec (to 14). Another region is an extract published by
21
+ `tools/map-assets.mjs` (krizaka-ui) and passed as `region={{ url, maxzoom }}`. The attribution (OpenStreetMap, ODbL;
22
+ Protomaps) is drawn by the components — never hide it.
23
+
24
+ ## Recipes
25
+
26
+ ```tsx
27
+ import { Map, Marker, StaticMap, LocationPicker } from "@krizaka/ui/map";
28
+
29
+ <Map label={t("pickup.title")} center={[-73.59, 45.52]} zoom={13} brand="orochia" className="h-80"
30
+ fallback={<StaticMap label={t("pickup.title")} center={[-73.59, 45.52]} zoom={13} places={spots} />}>
31
+ {spots.map((s) => <Marker key={s.id} position={s.position} label={s.label} selected={s.id === chosen} onPress={() => setChosen(s.id)} />)}
32
+ </Map>
33
+ <LocationPicker label={t("meet.point")} locale={locale} value={point} onValueChange={setPoint} radius={1000}
34
+ labels={{ nearMe: t("meet.nearMe"), denied: t("meet.denied"), distance: (d) => t("meet.distance", { d }) }} />
35
+ ```
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cn.ts","../src/floating.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cnMerge, type TWMergeConfig } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * The preset's own utilities, told to the merge engine: the material (BRAND.md §6: `bg-sheen`, `bg-fill-shade`,\n * `bg-halo` are background images; `shadow-raised` · `-floating` · `-overlay` · `-glow` are shadows; `inset-shadow-edge`\n * · `-edge-fill` · `-well` are inset shadows). Unknown, tailwind-merge would take `bg-sheen` for a colour and drop the\n * `bg-surface-2` it lies on.\n */\nexport const twMergeConfig: TWMergeConfig = {\n extend: {\n classGroups: {\n \"bg-image\": [\"bg-sheen\", \"bg-fill-shade\", \"bg-halo\"],\n shadow: [\"shadow-raised\", \"shadow-floating\", \"shadow-overlay\", \"shadow-glow\", \"shadow-glow-lg\"],\n \"inset-shadow\": [\"inset-shadow-edge\", \"inset-shadow-edge-fill\", \"inset-shadow-well\"],\n },\n },\n};\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n * tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer):\n * hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean\n * install of the packed package.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return cnMerge(clsx(inputs))({ twMergeConfig }) ?? \"\";\n}\n","// The one surface of everything that floats next to its trigger (popover, menu, tooltip): a raised surface, a border,\n// the large shadow and the `kz-pop` entrance from the side Radix measured (`--radix-*-transform-origin`).\nexport const floating =\n \"kz-pop z-50 rounded-lg border border-border-default bg-surface-2 text-fg shadow-lg outline-hidden\";\n"],"mappings":";;;AAAA,SAA0B,YAAY;AACtC,SAAS,eAAmC;AAUrC,IAAM,gBAA+B;AAAA,EAC1C,QAAQ;AAAA,IACN,aAAa;AAAA,MACX,YAAY,CAAC,YAAY,iBAAiB,SAAS;AAAA,MACnD,QAAQ,CAAC,iBAAiB,mBAAmB,kBAAkB,eAAe,gBAAgB;AAAA,MAC9F,gBAAgB,CAAC,qBAAqB,0BAA0B,mBAAmB;AAAA,IACrF;AAAA,EACF;AACF;AASO,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,KAAK;AACrD;;;AC5BO,IAAM,WACX;","names":[]}