@krizaka/ui 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/dist/activity-feed.d.ts +199 -0
  2. package/dist/activity-feed.js +155 -0
  3. package/dist/activity-feed.js.map +1 -0
  4. package/dist/argument-card.js +3 -3
  5. package/dist/chunk-7Z4KHPFC.js +42 -0
  6. package/dist/chunk-7Z4KHPFC.js.map +1 -0
  7. package/dist/data-table.js +98 -131
  8. package/dist/data-table.js.map +1 -1
  9. package/dist/description-list.d.ts +105 -0
  10. package/dist/description-list.js +49 -0
  11. package/dist/description-list.js.map +1 -0
  12. package/dist/index.js +13 -66
  13. package/dist/index.js.map +1 -1
  14. package/dist/kanban.d.ts +132 -0
  15. package/dist/kanban.js +187 -0
  16. package/dist/kanban.js.map +1 -0
  17. package/dist/list.d.ts +153 -0
  18. package/dist/list.js +130 -0
  19. package/dist/list.js.map +1 -0
  20. package/dist/map.d.ts +463 -0
  21. package/dist/map.js +952 -0
  22. package/dist/map.js.map +1 -0
  23. package/dist/motion.css +12 -1
  24. package/dist/native/map.d.ts +200 -0
  25. package/dist/native/map.js +673 -0
  26. package/dist/native/map.js.map +1 -0
  27. package/dist/native/media-picker.d.ts +58 -0
  28. package/dist/native/media-picker.js +63 -0
  29. package/dist/native/media-picker.js.map +1 -0
  30. package/dist/native.d.ts +568 -6
  31. package/dist/native.js +1989 -868
  32. package/dist/native.js.map +1 -1
  33. package/dist/page-hero.js +3 -3
  34. package/dist/stat.d.ts +31 -2
  35. package/dist/stat.js +21 -4
  36. package/dist/stat.js.map +1 -1
  37. package/dist/tree-view.d.ts +111 -0
  38. package/dist/tree-view.js +154 -0
  39. package/dist/tree-view.js.map +1 -0
  40. package/package.json +147 -10
  41. package/registry/achievement.json +1 -1
  42. package/registry/action-bar.json +1 -1
  43. package/registry/action-sheet.json +121 -0
  44. package/registry/activity-feed.json +468 -0
  45. package/registry/alert.json +1 -1
  46. package/registry/app-shell.json +1 -1
  47. package/registry/argument-card.json +1 -1
  48. package/registry/audio-player.json +1 -1
  49. package/registry/auth-layout.json +1 -1
  50. package/registry/avatar.json +58 -3
  51. package/registry/badge.json +1 -1
  52. package/registry/button.json +1 -1
  53. package/registry/card-grid.json +1 -1
  54. package/registry/card.json +1 -1
  55. package/registry/catalogue-page.json +1 -1
  56. package/registry/changelog-page.json +1 -1
  57. package/registry/checkbox.json +1 -1
  58. package/registry/chip-link.json +1 -1
  59. package/registry/chip.json +1 -1
  60. package/registry/choice-grid.json +1 -1
  61. package/registry/code-block.json +1 -1
  62. package/registry/combobox.json +1 -1
  63. package/registry/command.json +1 -1
  64. package/registry/component-page.json +1 -1
  65. package/registry/confirm-button.json +1 -1
  66. package/registry/contact-page.json +1 -1
  67. package/registry/continue-prompt.json +1 -1
  68. package/registry/countdown.json +1 -1
  69. package/registry/cta-panel.json +1 -1
  70. package/registry/dashboard-layout.json +1 -1
  71. package/registry/data-table.json +1 -1
  72. package/registry/date-picker.json +2 -2
  73. package/registry/decision-list.json +1 -1
  74. package/registry/description-list.json +232 -0
  75. package/registry/detail-layout.json +1 -1
  76. package/registry/dialog.json +1 -1
  77. package/registry/docs-article-page.json +1 -1
  78. package/registry/docs-hub-page.json +1 -1
  79. package/registry/docs-layout.json +1 -1
  80. package/registry/dropdown-menu.json +1 -1
  81. package/registry/empty-state.json +1 -1
  82. package/registry/error-page.json +1 -1
  83. package/registry/examples/action-sheet/native/video-actions.d.ts +4 -0
  84. package/registry/examples/action-sheet/native/video-actions.dark.png +0 -0
  85. package/registry/examples/action-sheet/native/video-actions.js +30 -0
  86. package/registry/examples/action-sheet/native/video-actions.light.png +0 -0
  87. package/registry/examples/action-sheet/native/video-actions.tsx +24 -0
  88. package/registry/examples/activity-feed/job-activity.d.ts +4 -0
  89. package/registry/examples/activity-feed/job-activity.js +21 -0
  90. package/registry/examples/activity-feed/job-activity.tsx +17 -0
  91. package/registry/examples/activity-feed/live.d.ts +4 -0
  92. package/registry/examples/activity-feed/live.js +23 -0
  93. package/registry/examples/activity-feed/live.tsx +24 -0
  94. package/registry/examples/activity-feed/native/notifications.d.ts +4 -0
  95. package/registry/examples/activity-feed/native/notifications.dark.png +0 -0
  96. package/registry/examples/activity-feed/native/notifications.js +18 -0
  97. package/registry/examples/activity-feed/native/notifications.light.png +0 -0
  98. package/registry/examples/activity-feed/native/notifications.tsx +18 -0
  99. package/registry/examples/activity-feed/timeline.d.ts +4 -0
  100. package/registry/examples/activity-feed/timeline.js +25 -0
  101. package/registry/examples/activity-feed/timeline.tsx +19 -0
  102. package/registry/examples/avatar/native/presence.d.ts +4 -0
  103. package/registry/examples/avatar/native/presence.dark.png +0 -0
  104. package/registry/examples/avatar/native/presence.js +18 -0
  105. package/registry/examples/avatar/native/presence.light.png +0 -0
  106. package/registry/examples/avatar/native/presence.tsx +15 -0
  107. package/registry/examples/description-list/job-details.d.ts +4 -0
  108. package/registry/examples/description-list/job-details.js +23 -0
  109. package/registry/examples/description-list/job-details.tsx +17 -0
  110. package/registry/examples/description-list/key-value-grid.d.ts +4 -0
  111. package/registry/examples/description-list/key-value-grid.js +22 -0
  112. package/registry/examples/description-list/key-value-grid.tsx +16 -0
  113. package/registry/examples/description-list/native/job-details.d.ts +4 -0
  114. package/registry/examples/description-list/native/job-details.dark.png +0 -0
  115. package/registry/examples/description-list/native/job-details.js +33 -0
  116. package/registry/examples/description-list/native/job-details.light.png +0 -0
  117. package/registry/examples/description-list/native/job-details.tsx +24 -0
  118. package/registry/examples/description-list/receipt.d.ts +4 -0
  119. package/registry/examples/description-list/receipt.js +23 -0
  120. package/registry/examples/description-list/receipt.tsx +17 -0
  121. package/registry/examples/fab/native/extended.d.ts +4 -0
  122. package/registry/examples/fab/native/extended.dark.png +0 -0
  123. package/registry/examples/fab/native/extended.js +18 -0
  124. package/registry/examples/fab/native/extended.light.png +0 -0
  125. package/registry/examples/fab/native/extended.tsx +23 -0
  126. package/registry/examples/header/native/large-title.d.ts +4 -0
  127. package/registry/examples/header/native/large-title.dark.png +0 -0
  128. package/registry/examples/header/native/large-title.js +23 -0
  129. package/registry/examples/header/native/large-title.light.png +0 -0
  130. package/registry/examples/header/native/large-title.tsx +31 -0
  131. package/registry/examples/image-viewer/native/gallery.d.ts +4 -0
  132. package/registry/examples/image-viewer/native/gallery.dark.png +0 -0
  133. package/registry/examples/image-viewer/native/gallery.js +22 -0
  134. package/registry/examples/image-viewer/native/gallery.light.png +0 -0
  135. package/registry/examples/image-viewer/native/gallery.tsx +21 -0
  136. package/registry/examples/kanban/moderation.d.ts +4 -0
  137. package/registry/examples/kanban/moderation.js +35 -0
  138. package/registry/examples/kanban/moderation.tsx +37 -0
  139. package/registry/examples/list/jobs.d.ts +4 -0
  140. package/registry/examples/list/jobs.js +35 -0
  141. package/registry/examples/list/jobs.tsx +33 -0
  142. package/registry/examples/list/selectable.d.ts +4 -0
  143. package/registry/examples/list/selectable.js +33 -0
  144. package/registry/examples/list/selectable.tsx +30 -0
  145. package/registry/examples/list/virtualized.d.ts +4 -0
  146. package/registry/examples/list/virtualized.js +22 -0
  147. package/registry/examples/list/virtualized.tsx +17 -0
  148. package/registry/examples/loader/native/block.d.ts +4 -0
  149. package/registry/examples/loader/native/block.dark.png +0 -0
  150. package/registry/examples/loader/native/block.js +12 -0
  151. package/registry/examples/loader/native/block.light.png +0 -0
  152. package/registry/examples/loader/native/block.tsx +11 -0
  153. package/registry/examples/loader/native/job-wait.d.ts +4 -0
  154. package/registry/examples/loader/native/job-wait.dark.png +0 -0
  155. package/registry/examples/loader/native/job-wait.js +17 -0
  156. package/registry/examples/loader/native/job-wait.light.png +0 -0
  157. package/registry/examples/loader/native/job-wait.tsx +14 -0
  158. package/registry/examples/map/cluster.d.ts +4 -0
  159. package/registry/examples/map/cluster.js +16 -0
  160. package/registry/examples/map/cluster.tsx +18 -0
  161. package/registry/examples/map/location-picker.d.ts +4 -0
  162. package/registry/examples/map/location-picker.js +24 -0
  163. package/registry/examples/map/location-picker.tsx +22 -0
  164. package/registry/examples/map/native/location-picker.d.ts +4 -0
  165. package/registry/examples/map/native/location-picker.dark.png +0 -0
  166. package/registry/examples/map/native/location-picker.js +14 -0
  167. package/registry/examples/map/native/location-picker.light.png +0 -0
  168. package/registry/examples/map/native/location-picker.tsx +13 -0
  169. package/registry/examples/map/native/places.d.ts +4 -0
  170. package/registry/examples/map/native/places.dark.png +0 -0
  171. package/registry/examples/map/native/places.js +25 -0
  172. package/registry/examples/map/native/places.light.png +0 -0
  173. package/registry/examples/map/native/places.tsx +27 -0
  174. package/registry/examples/map/places.d.ts +4 -0
  175. package/registry/examples/map/places.js +28 -0
  176. package/registry/examples/map/places.tsx +28 -0
  177. package/registry/examples/map/static.d.ts +4 -0
  178. package/registry/examples/map/static.js +22 -0
  179. package/registry/examples/map/static.tsx +18 -0
  180. package/registry/examples/media-picker/native/story.d.ts +4 -0
  181. package/registry/examples/media-picker/native/story.dark.png +0 -0
  182. package/registry/examples/media-picker/native/story.js +30 -0
  183. package/registry/examples/media-picker/native/story.light.png +0 -0
  184. package/registry/examples/media-picker/native/story.tsx +26 -0
  185. package/registry/examples/meter/native/credits.d.ts +4 -0
  186. package/registry/examples/meter/native/credits.dark.png +0 -0
  187. package/registry/examples/meter/native/credits.js +15 -0
  188. package/registry/examples/meter/native/credits.light.png +0 -0
  189. package/registry/examples/meter/native/credits.tsx +12 -0
  190. package/registry/examples/meter/native/split-ring.d.ts +4 -0
  191. package/registry/examples/meter/native/split-ring.dark.png +0 -0
  192. package/registry/examples/meter/native/split-ring.js +24 -0
  193. package/registry/examples/meter/native/split-ring.light.png +0 -0
  194. package/registry/examples/meter/native/split-ring.tsx +19 -0
  195. package/registry/examples/number-ticker/native/balance.d.ts +4 -0
  196. package/registry/examples/number-ticker/native/balance.dark.png +0 -0
  197. package/registry/examples/number-ticker/native/balance.js +18 -0
  198. package/registry/examples/number-ticker/native/balance.light.png +0 -0
  199. package/registry/examples/number-ticker/native/balance.tsx +17 -0
  200. package/registry/examples/onboarding/native/first-launch.d.ts +4 -0
  201. package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
  202. package/registry/examples/onboarding/native/first-launch.js +23 -0
  203. package/registry/examples/onboarding/native/first-launch.light.png +0 -0
  204. package/registry/examples/onboarding/native/first-launch.tsx +19 -0
  205. package/registry/examples/otp-input/native/invalid.d.ts +4 -0
  206. package/registry/examples/otp-input/native/invalid.dark.png +0 -0
  207. package/registry/examples/otp-input/native/invalid.js +15 -0
  208. package/registry/examples/otp-input/native/invalid.light.png +0 -0
  209. package/registry/examples/otp-input/native/invalid.tsx +14 -0
  210. package/registry/examples/otp-input/native/verify.d.ts +4 -0
  211. package/registry/examples/otp-input/native/verify.dark.png +0 -0
  212. package/registry/examples/otp-input/native/verify.js +17 -0
  213. package/registry/examples/otp-input/native/verify.light.png +0 -0
  214. package/registry/examples/otp-input/native/verify.tsx +14 -0
  215. package/registry/examples/permission-prompt/native/blocked.d.ts +4 -0
  216. package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
  217. package/registry/examples/permission-prompt/native/blocked.js +25 -0
  218. package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
  219. package/registry/examples/permission-prompt/native/blocked.tsx +21 -0
  220. package/registry/examples/permission-prompt/native/camera.d.ts +4 -0
  221. package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
  222. package/registry/examples/permission-prompt/native/camera.js +25 -0
  223. package/registry/examples/permission-prompt/native/camera.light.png +0 -0
  224. package/registry/examples/permission-prompt/native/camera.tsx +21 -0
  225. package/registry/examples/pull-to-refresh/native/feed.d.ts +4 -0
  226. package/registry/examples/pull-to-refresh/native/feed.dark.png +0 -0
  227. package/registry/examples/pull-to-refresh/native/feed.js +14 -0
  228. package/registry/examples/pull-to-refresh/native/feed.light.png +0 -0
  229. package/registry/examples/pull-to-refresh/native/feed.tsx +19 -0
  230. package/registry/examples/search-field/native/cancel.d.ts +4 -0
  231. package/registry/examples/search-field/native/cancel.dark.png +0 -0
  232. package/registry/examples/search-field/native/cancel.js +14 -0
  233. package/registry/examples/search-field/native/cancel.light.png +0 -0
  234. package/registry/examples/search-field/native/cancel.tsx +13 -0
  235. package/registry/examples/stat/grid.d.ts +4 -0
  236. package/registry/examples/stat/grid.js +17 -0
  237. package/registry/examples/stat/grid.tsx +14 -0
  238. package/registry/examples/stepper/native/run.d.ts +4 -0
  239. package/registry/examples/stepper/native/run.dark.png +0 -0
  240. package/registry/examples/stepper/native/run.js +24 -0
  241. package/registry/examples/stepper/native/run.light.png +0 -0
  242. package/registry/examples/stepper/native/run.tsx +20 -0
  243. package/registry/examples/swipeable-row/native/conversation.d.ts +4 -0
  244. package/registry/examples/swipeable-row/native/conversation.dark.png +0 -0
  245. package/registry/examples/swipeable-row/native/conversation.js +30 -0
  246. package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
  247. package/registry/examples/swipeable-row/native/conversation.tsx +27 -0
  248. package/registry/examples/tab-bar/native/main-sections.d.ts +4 -0
  249. package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
  250. package/registry/examples/tab-bar/native/main-sections.js +29 -0
  251. package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
  252. package/registry/examples/tab-bar/native/main-sections.tsx +30 -0
  253. package/registry/examples/tabs/native/sections.d.ts +4 -0
  254. package/registry/examples/tabs/native/sections.dark.png +0 -0
  255. package/registry/examples/tabs/native/sections.js +23 -0
  256. package/registry/examples/tabs/native/sections.light.png +0 -0
  257. package/registry/examples/tabs/native/sections.tsx +19 -0
  258. package/registry/examples/tabs/native/segmented.d.ts +4 -0
  259. package/registry/examples/tabs/native/segmented.dark.png +0 -0
  260. package/registry/examples/tabs/native/segmented.js +22 -0
  261. package/registry/examples/tabs/native/segmented.light.png +0 -0
  262. package/registry/examples/tabs/native/segmented.tsx +18 -0
  263. package/registry/examples/toast/native/snackbar.d.ts +4 -0
  264. package/registry/examples/toast/native/snackbar.dark.png +0 -0
  265. package/registry/examples/toast/native/snackbar.js +23 -0
  266. package/registry/examples/toast/native/snackbar.light.png +0 -0
  267. package/registry/examples/toast/native/snackbar.tsx +21 -0
  268. package/registry/examples/tree-view/docs.d.ts +4 -0
  269. package/registry/examples/tree-view/docs.js +24 -0
  270. package/registry/examples/tree-view/docs.tsx +22 -0
  271. package/registry/examples/tree-view/lazy.d.ts +4 -0
  272. package/registry/examples/tree-view/lazy.js +21 -0
  273. package/registry/examples/tree-view/lazy.tsx +19 -0
  274. package/registry/fab.json +122 -0
  275. package/registry/field.json +1 -1
  276. package/registry/file-upload.json +2 -2
  277. package/registry/filter-bar.json +1 -1
  278. package/registry/form.json +2 -2
  279. package/registry/gallery-page.json +1 -1
  280. package/registry/glow-card.json +1 -1
  281. package/registry/goal-gauge.json +1 -1
  282. package/registry/header.json +137 -0
  283. package/registry/how-it-works-page.json +1 -1
  284. package/registry/image-cropper.json +1 -1
  285. package/registry/image-viewer.json +107 -0
  286. package/registry/index.json +299 -25
  287. package/registry/iso.json +1 -1
  288. package/registry/kanban.json +253 -0
  289. package/registry/kbd.json +1 -1
  290. package/registry/landing-page.json +1 -1
  291. package/registry/landscape.json +1 -1
  292. package/registry/legal-page.json +1 -1
  293. package/registry/link-card.json +1 -1
  294. package/registry/list.json +367 -30
  295. package/registry/loader.json +157 -4
  296. package/registry/longform-page.json +1 -1
  297. package/registry/map.json +1368 -0
  298. package/registry/marketing-layout.json +1 -1
  299. package/registry/marquee.json +1 -1
  300. package/registry/mascot-quote.json +1 -1
  301. package/registry/mascot-state.json +1 -1
  302. package/registry/mascots.json +1 -1
  303. package/registry/media-capture.json +1 -1
  304. package/registry/media-picker.json +129 -0
  305. package/registry/meter.json +136 -4
  306. package/registry/nav-bar.json +1 -1
  307. package/registry/number-ticker.json +96 -4
  308. package/registry/onboarding.json +95 -0
  309. package/registry/otp-input.json +150 -0
  310. package/registry/page-header.json +1 -1
  311. package/registry/page-hero.json +1 -1
  312. package/registry/page.json +1 -1
  313. package/registry/pagination.json +1 -1
  314. package/registry/permission-prompt.json +172 -0
  315. package/registry/pointer-light.json +1 -1
  316. package/registry/popover.json +1 -1
  317. package/registry/pricing-page.json +1 -1
  318. package/registry/product-page.json +1 -1
  319. package/registry/profile-card.json +1 -1
  320. package/registry/progress.json +2 -2
  321. package/registry/promise-card.json +1 -1
  322. package/registry/pull-to-refresh.json +74 -0
  323. package/registry/radio-group.json +1 -1
  324. package/registry/scroll-stage.json +1 -1
  325. package/registry/search-field.json +30 -3
  326. package/registry/section-backdrop.json +1 -1
  327. package/registry/separator.json +1 -1
  328. package/registry/settings-layout.json +1 -1
  329. package/registry/skeleton.json +1 -1
  330. package/registry/slider.json +1 -1
  331. package/registry/slot.json +1 -1
  332. package/registry/spinner.json +1 -1
  333. package/registry/split-view.json +1 -1
  334. package/registry/stage-banner.json +1 -1
  335. package/registry/stat.json +68 -5
  336. package/registry/status-page.json +1 -1
  337. package/registry/stepper.json +75 -4
  338. package/registry/swipeable-row.json +124 -0
  339. package/registry/switch.json +1 -1
  340. package/registry/tab-bar.json +115 -0
  341. package/registry/tabs.json +94 -4
  342. package/registry/tag-input.json +1 -1
  343. package/registry/terminal-replay.json +1 -1
  344. package/registry/theme.json +8 -1
  345. package/registry/toast.json +17 -3
  346. package/registry/toc.json +1 -1
  347. package/registry/tooltip.json +1 -1
  348. package/registry/tree-view.json +291 -0
  349. package/registry/video-player.json +1 -1
  350. package/registry/video-trimmer.json +1 -1
  351. package/registry/virtual.json +1 -1
  352. package/skills/map/SKILL.md +35 -0
package/dist/page-hero.js CHANGED
@@ -1,12 +1,12 @@
1
- import {
2
- Page
3
- } from "./chunk-DGQMDJXK.js";
4
1
  import {
5
2
  BlockLink
6
3
  } from "./chunk-2AGSO3WH.js";
7
4
  import {
8
5
  ArrowGlyph
9
6
  } from "./chunk-XCBVFMNV.js";
7
+ import {
8
+ Page
9
+ } from "./chunk-DGQMDJXK.js";
10
10
  import {
11
11
  SectionBackdrop
12
12
  } from "./chunk-XVLWVTQA.js";
package/dist/stat.d.ts CHANGED
@@ -20,6 +20,7 @@ declare const stat: tailwind_variants.TVReturnType<{
20
20
  meta: string;
21
21
  trend: string;
22
22
  hint: string;
23
+ chart: string;
23
24
  }, undefined, {
24
25
  trend: {
25
26
  up: {
@@ -39,6 +40,7 @@ declare const stat: tailwind_variants.TVReturnType<{
39
40
  meta: string;
40
41
  trend: string;
41
42
  hint: string;
43
+ chart: string;
42
44
  }, tailwind_variants.TVReturnTypeLike<{
43
45
  trend: {
44
46
  up: {
@@ -58,6 +60,7 @@ declare const stat: tailwind_variants.TVReturnType<{
58
60
  meta: string;
59
61
  trend: string;
60
62
  hint: string;
63
+ chart: string;
61
64
  }>>;
62
65
  type StatTrend = "up" | "down" | "flat";
63
66
  type StatProps = Omit<React.ComponentProps<"div">, "children"> & {
@@ -71,7 +74,33 @@ type StatProps = Omit<React.ComponentProps<"div">, "children"> & {
71
74
  trend?: StatTrend;
72
75
  /** The change, in words, as read and shown (e.g. "+12 % vs last week") — the arrow alone says nothing. */
73
76
  trendLabel?: React.ReactNode;
77
+ /** Under the figure: a `Sparkline` of @krizaka/charts (its own accessible summary), a `Meter`. */
78
+ chart?: React.ReactNode;
74
79
  };
75
- declare function Stat({ label, value, hint, trend, trendLabel, className, ...props }: StatProps): React.JSX.Element;
80
+ declare function Stat({ label, value, hint, trend, trendLabel, chart, className, ...props }: StatProps): React.JSX.Element;
81
+ declare const statGrid: tailwind_variants.TVReturnType<{
82
+ divided: {
83
+ true: "gap-px bg-border-subtle [&>*]:bg-surface-1 [&>*]:p-5";
84
+ false: "gap-6 p-5";
85
+ };
86
+ }, undefined, "grid w-full grid-cols-[repeat(auto-fit,minmax(var(--kz-stat-min,11rem),1fr))] overflow-hidden rounded-xl border border-border-default bg-surface-1", {
87
+ divided: {
88
+ true: "gap-px bg-border-subtle [&>*]:bg-surface-1 [&>*]:p-5";
89
+ false: "gap-6 p-5";
90
+ };
91
+ }, undefined, tailwind_variants.TVReturnTypeLike<{
92
+ divided: {
93
+ true: "gap-px bg-border-subtle [&>*]:bg-surface-1 [&>*]:p-5";
94
+ false: "gap-6 p-5";
95
+ };
96
+ }, undefined>>;
97
+ type StatGridProps = React.ComponentProps<"div"> & {
98
+ /** Hairlines between the stats (default) or space only. */
99
+ divided?: boolean;
100
+ /** The narrowest a stat may be before the row wraps, in rem. Default 11. */
101
+ minWidth?: number;
102
+ };
103
+ /** A row of key figures that wraps with the width: a dashboard's head. The stats are its children. */
104
+ declare function StatGrid({ divided, minWidth, className, style, ...props }: StatGridProps): React.JSX.Element;
76
105
 
77
- export { Stat, type StatProps, type StatTrend, stat };
106
+ export { Stat, StatGrid, type StatGridProps, type StatProps, type StatTrend, stat, statGrid };
package/dist/stat.js CHANGED
@@ -10,7 +10,8 @@ var stat = tv({
10
10
  // The status tokens are too light for small text on a light surface: the words stay a text role, the arrow carries
11
11
  // the direction's colour.
12
12
  trend: "inline-flex items-center gap-1 font-semibold text-fg [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0",
13
- hint: "text-fg-secondary"
13
+ hint: "text-fg-secondary",
14
+ chart: "mt-2 h-10 w-full min-w-0"
14
15
  },
15
16
  variants: {
16
17
  trend: {
@@ -21,7 +22,7 @@ var stat = tv({
21
22
  }
22
23
  });
23
24
  var ARROW = { up: "M7 17 17 7M8 7h9v9", down: "M7 7l10 10M17 8v9H8", flat: "M5 12h14M13 6l6 6-6 6" };
24
- function Stat({ label, value, hint, trend, trendLabel, className, ...props }) {
25
+ function Stat({ label, value, hint, trend, trendLabel, chart, className, ...props }) {
25
26
  const s = stat({ trend });
26
27
  return /* @__PURE__ */ jsxs("div", { "data-trend": trend, className: s.root({ className }), ...props, children: [
27
28
  /* @__PURE__ */ jsx("p", { className: s.label(), children: label }),
@@ -32,11 +33,27 @@ function Stat({ label, value, hint, trend, trendLabel, className, ...props }) {
32
33
  trendLabel
33
34
  ] }),
34
35
  hint && /* @__PURE__ */ jsx("span", { className: s.hint(), children: hint })
35
- ] })
36
+ ] }),
37
+ chart ? /* @__PURE__ */ jsx("div", { className: s.chart(), children: chart }) : null
36
38
  ] });
37
39
  }
40
+ var statGrid = tv({
41
+ base: "grid w-full grid-cols-[repeat(auto-fit,minmax(var(--kz-stat-min,11rem),1fr))] overflow-hidden rounded-xl border border-border-default bg-surface-1",
42
+ variants: {
43
+ divided: {
44
+ true: "gap-px bg-border-subtle [&>*]:bg-surface-1 [&>*]:p-5",
45
+ false: "gap-6 p-5"
46
+ }
47
+ },
48
+ defaultVariants: { divided: true }
49
+ });
50
+ function StatGrid({ divided, minWidth = 11, className, style, ...props }) {
51
+ return /* @__PURE__ */ jsx("div", { className: statGrid({ divided, className }), style: { ...style, ["--kz-stat-min"]: `${minWidth}rem` }, ...props });
52
+ }
38
53
  export {
39
54
  Stat,
40
- stat
55
+ StatGrid,
56
+ stat,
57
+ statGrid
41
58
  };
42
59
  //# sourceMappingURL=stat.js.map
package/dist/stat.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stat/stat.tsx"],"sourcesContent":["// Server-safe. A key figure: a label, the value in tabular digits, a hint, a trend. Every word is a prop.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const stat = tv({\n slots: {\n root: \"flex min-w-0 flex-col gap-1\",\n label: \"text-xs font-semibold uppercase tracking-wider text-fg-secondary\",\n value: \"font-display text-2xl font-black tabular-nums text-fg\",\n meta: \"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs\",\n // The status tokens are too light for small text on a light surface: the words stay a text role, the arrow carries\n // the direction's colour.\n trend: \"inline-flex items-center gap-1 font-semibold text-fg [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0\",\n hint: \"text-fg-secondary\",\n },\n variants: {\n trend: {\n up: { trend: \"[&>svg]:text-success\" },\n down: { trend: \"[&>svg]:text-danger\" },\n flat: { trend: \"[&>svg]:text-fg-secondary\" },\n },\n },\n});\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nconst ARROW: Record<StatTrend, string> = { up: \"M7 17 17 7M8 7h9v9\", down: \"M7 7l10 10M17 8v9H8\", flat: \"M5 12h14M13 6l6 6-6 6\" };\n\nexport type StatProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n /** What the figure is (\"Revenue\"), above it. */\n label: React.ReactNode;\n /** The figure, formatted by the app, in tabular digits. */\n value: React.ReactNode;\n /** A line under the value: the period, the comparison. */\n hint?: React.ReactNode;\n /** The direction of the change; its arrow is decorative. */\n trend?: StatTrend;\n /** The change, in words, as read and shown (e.g. \"+12 % vs last week\") — the arrow alone says nothing. */\n trendLabel?: React.ReactNode;\n};\n\nexport function Stat({ label, value, hint, trend, trendLabel, className, ...props }: StatProps) {\n const s = stat({ trend });\n return (\n <div data-trend={trend} className={s.root({ className })} {...props}>\n <p className={s.label()}>{label}</p>\n <p className={s.value()}>{value}</p>\n {(trendLabel || hint) && (\n <p className={s.meta()}>\n {trend && trendLabel && (\n <span className={s.trend()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d={ARROW[trend]} />\n </svg>\n {trendLabel}\n </span>\n )}\n {hint && <span className={s.hint()}>{hint}</span>}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";AAEA,SAAS,UAAU;AA2Cb,cAKM,YALN;AAzCC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA;AAAA;AAAA,IAGN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,MACL,IAAI,EAAE,OAAO,uBAAuB;AAAA,MACpC,MAAM,EAAE,OAAO,sBAAsB;AAAA,MACrC,MAAM,EAAE,OAAO,4BAA4B;AAAA,IAC7C;AAAA,EACF;AACF,CAAC;AAID,IAAM,QAAmC,EAAE,IAAI,sBAAsB,MAAM,uBAAuB,MAAM,wBAAwB;AAezH,SAAS,KAAK,EAAE,OAAO,OAAO,MAAM,OAAO,YAAY,WAAW,GAAG,MAAM,GAAc;AAC9F,QAAM,IAAI,KAAK,EAAE,MAAM,CAAC;AACxB,SACE,qBAAC,SAAI,cAAY,OAAO,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC5D;AAAA,wBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,IAChC,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,KAC9B,cAAc,SACd,qBAAC,OAAE,WAAW,EAAE,KAAK,GAClB;AAAA,eAAS,cACR,qBAAC,UAAK,WAAW,EAAE,MAAM,GACvB;AAAA,4BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAG,MAAM,KAAK,GAAG,GACzB;AAAA,QACC;AAAA,SACH;AAAA,MAED,QAAQ,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,OAC5C;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/stat/stat.tsx"],"sourcesContent":["// Server-safe. A key figure: a label, the value in tabular digits, a hint, a trend. Every word is a prop.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const stat = tv({\n slots: {\n root: \"flex min-w-0 flex-col gap-1\",\n label: \"text-xs font-semibold uppercase tracking-wider text-fg-secondary\",\n value: \"font-display text-2xl font-black tabular-nums text-fg\",\n meta: \"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs\",\n // The status tokens are too light for small text on a light surface: the words stay a text role, the arrow carries\n // the direction's colour.\n trend: \"inline-flex items-center gap-1 font-semibold text-fg [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0\",\n hint: \"text-fg-secondary\",\n chart: \"mt-2 h-10 w-full min-w-0\",\n },\n variants: {\n trend: {\n up: { trend: \"[&>svg]:text-success\" },\n down: { trend: \"[&>svg]:text-danger\" },\n flat: { trend: \"[&>svg]:text-fg-secondary\" },\n },\n },\n});\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nconst ARROW: Record<StatTrend, string> = { up: \"M7 17 17 7M8 7h9v9\", down: \"M7 7l10 10M17 8v9H8\", flat: \"M5 12h14M13 6l6 6-6 6\" };\n\nexport type StatProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n /** What the figure is (\"Revenue\"), above it. */\n label: React.ReactNode;\n /** The figure, formatted by the app, in tabular digits. */\n value: React.ReactNode;\n /** A line under the value: the period, the comparison. */\n hint?: React.ReactNode;\n /** The direction of the change; its arrow is decorative. */\n trend?: StatTrend;\n /** The change, in words, as read and shown (e.g. \"+12 % vs last week\") — the arrow alone says nothing. */\n trendLabel?: React.ReactNode;\n /** Under the figure: a `Sparkline` of @krizaka/charts (its own accessible summary), a `Meter`. */\n chart?: React.ReactNode;\n};\n\nexport function Stat({ label, value, hint, trend, trendLabel, chart, className, ...props }: StatProps) {\n const s = stat({ trend });\n return (\n <div data-trend={trend} className={s.root({ className })} {...props}>\n <p className={s.label()}>{label}</p>\n <p className={s.value()}>{value}</p>\n {(trendLabel || hint) && (\n <p className={s.meta()}>\n {trend && trendLabel && (\n <span className={s.trend()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d={ARROW[trend]} />\n </svg>\n {trendLabel}\n </span>\n )}\n {hint && <span className={s.hint()}>{hint}</span>}\n </p>\n )}\n {chart ? <div className={s.chart()}>{chart}</div> : null}\n </div>\n );\n}\n\nexport const statGrid = tv({\n base: \"grid w-full grid-cols-[repeat(auto-fit,minmax(var(--kz-stat-min,11rem),1fr))] overflow-hidden rounded-xl border border-border-default bg-surface-1\",\n variants: {\n divided: {\n true: \"gap-px bg-border-subtle [&>*]:bg-surface-1 [&>*]:p-5\",\n false: \"gap-6 p-5\",\n },\n },\n defaultVariants: { divided: true },\n});\n\nexport type StatGridProps = React.ComponentProps<\"div\"> & {\n /** Hairlines between the stats (default) or space only. */\n divided?: boolean;\n /** The narrowest a stat may be before the row wraps, in rem. Default 11. */\n minWidth?: number;\n};\n\n/** A row of key figures that wraps with the width: a dashboard's head. The stats are its children. */\nexport function StatGrid({ divided, minWidth = 11, className, style, ...props }: StatGridProps) {\n return <div className={statGrid({ divided, className })} style={{ ...style, [\"--kz-stat-min\" as string]: `${minWidth}rem` }} {...props} />;\n}\n"],"mappings":";AAEA,SAAS,UAAU;AA8Cb,cAKM,YALN;AA5CC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA;AAAA;AAAA,IAGN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,MACL,IAAI,EAAE,OAAO,uBAAuB;AAAA,MACpC,MAAM,EAAE,OAAO,sBAAsB;AAAA,MACrC,MAAM,EAAE,OAAO,4BAA4B;AAAA,IAC7C;AAAA,EACF;AACF,CAAC;AAID,IAAM,QAAmC,EAAE,IAAI,sBAAsB,MAAM,uBAAuB,MAAM,wBAAwB;AAiBzH,SAAS,KAAK,EAAE,OAAO,OAAO,MAAM,OAAO,YAAY,OAAO,WAAW,GAAG,MAAM,GAAc;AACrG,QAAM,IAAI,KAAK,EAAE,MAAM,CAAC;AACxB,SACE,qBAAC,SAAI,cAAY,OAAO,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC5D;AAAA,wBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,IAChC,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,KAC9B,cAAc,SACd,qBAAC,OAAE,WAAW,EAAE,KAAK,GAClB;AAAA,eAAS,cACR,qBAAC,UAAK,WAAW,EAAE,MAAM,GACvB;AAAA,4BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAG,MAAM,KAAK,GAAG,GACzB;AAAA,QACC;AAAA,SACH;AAAA,MAED,QAAQ,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,OAC5C;AAAA,IAED,QAAQ,oBAAC,SAAI,WAAW,EAAE,MAAM,GAAI,iBAAM,IAAS;AAAA,KACtD;AAEJ;AAEO,IAAM,WAAW,GAAG;AAAA,EACzB,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,KAAK;AACnC,CAAC;AAUM,SAAS,SAAS,EAAE,SAAS,WAAW,IAAI,WAAW,OAAO,GAAG,MAAM,GAAkB;AAC9F,SAAO,oBAAC,SAAI,WAAW,SAAS,EAAE,SAAS,UAAU,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,eAAyB,GAAG,GAAG,QAAQ,MAAM,GAAI,GAAG,OAAO;AAC1I;","names":[]}
@@ -0,0 +1,111 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const treeView: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ root?: tailwind_variants.ClassValue;
8
+ group?: tailwind_variants.ClassValue;
9
+ toggle?: tailwind_variants.ClassValue;
10
+ icon?: tailwind_variants.ClassValue;
11
+ label?: tailwind_variants.ClassValue;
12
+ meta?: tailwind_variants.ClassValue;
13
+ row?: tailwind_variants.ClassValue;
14
+ };
15
+ };
16
+ } | {
17
+ [x: string]: {
18
+ [x: string]: tailwind_variants.ClassValue | {
19
+ root?: tailwind_variants.ClassValue;
20
+ group?: tailwind_variants.ClassValue;
21
+ toggle?: tailwind_variants.ClassValue;
22
+ icon?: tailwind_variants.ClassValue;
23
+ label?: tailwind_variants.ClassValue;
24
+ meta?: tailwind_variants.ClassValue;
25
+ row?: tailwind_variants.ClassValue;
26
+ };
27
+ };
28
+ } | {}, {
29
+ root: string;
30
+ group: string;
31
+ row: string;
32
+ toggle: string;
33
+ icon: string;
34
+ label: string;
35
+ meta: string;
36
+ }, undefined, {
37
+ [key: string]: {
38
+ [key: string]: tailwind_variants.ClassValue | {
39
+ root?: tailwind_variants.ClassValue;
40
+ group?: tailwind_variants.ClassValue;
41
+ toggle?: tailwind_variants.ClassValue;
42
+ icon?: tailwind_variants.ClassValue;
43
+ label?: tailwind_variants.ClassValue;
44
+ meta?: tailwind_variants.ClassValue;
45
+ row?: tailwind_variants.ClassValue;
46
+ };
47
+ };
48
+ } | {}, {
49
+ root: string;
50
+ group: string;
51
+ row: string;
52
+ toggle: string;
53
+ icon: string;
54
+ label: string;
55
+ meta: string;
56
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
57
+ root: string;
58
+ group: string;
59
+ row: string;
60
+ toggle: string;
61
+ icon: string;
62
+ label: string;
63
+ meta: string;
64
+ }>>;
65
+ type TreeNode = {
66
+ /** A stable id. */
67
+ id: string;
68
+ /** Its name — passed translated. */
69
+ label: string;
70
+ /** A decorative icon before the name. */
71
+ icon?: React.ReactNode;
72
+ /** A detail after the name (a count, a size). */
73
+ meta?: React.ReactNode;
74
+ /** Its children; `undefined` for a leaf. With `hasChildren`, they load when it opens (`onLoadChildren`). */
75
+ children?: readonly TreeNode[];
76
+ /** A branch whose children are not loaded yet. */
77
+ hasChildren?: boolean;
78
+ /** Cannot be selected. */
79
+ disabled?: boolean;
80
+ };
81
+ type TreeViewProps = {
82
+ /** The roots. */
83
+ nodes: readonly TreeNode[];
84
+ /** The tree's accessible name (“Documentation”). */
85
+ "aria-label": string;
86
+ /** The ids of the open branches (controlled). */
87
+ expanded?: readonly string[];
88
+ /** The ids open at first, uncontrolled. */
89
+ defaultExpanded?: readonly string[];
90
+ /** Called with the open branches. */
91
+ onExpandedChange?: (expanded: string[]) => void;
92
+ /** The selected node (controlled). */
93
+ selected?: string | null;
94
+ /** The selected node at first, uncontrolled. */
95
+ defaultSelected?: string | null;
96
+ /** Called when a node is chosen (click, Enter or Space): navigate, open the file. */
97
+ onSelect?: (node: TreeNode) => void;
98
+ /** Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`. */
99
+ onLoadChildren?: (node: TreeNode) => void;
100
+ /** The words of a branch that is loading (“Loading”). */
101
+ loadingLabel?: string;
102
+ /** Classes merged on the tree. */
103
+ className?: string;
104
+ };
105
+ /**
106
+ * A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→
107
+ * opens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.
108
+ */
109
+ declare function TreeView({ nodes, "aria-label": label, expanded: expandedProp, defaultExpanded, onExpandedChange, selected: selectedProp, defaultSelected, onSelect, onLoadChildren, loadingLabel, className, }: TreeViewProps): React.JSX.Element;
110
+
111
+ export { type TreeNode, TreeView, type TreeViewProps, treeView };
@@ -0,0 +1,154 @@
1
+ "use client";
2
+ import {
3
+ useControllable
4
+ } from "./chunk-BRKMQ6JV.js";
5
+ import {
6
+ ChevronGlyph
7
+ } from "./chunk-CPA5CF35.js";
8
+
9
+ // src/tree-view/tree-view.tsx
10
+ import * as React from "react";
11
+ import { tv } from "tailwind-variants";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ var treeView = tv({
14
+ slots: {
15
+ root: "m-0 list-none p-0 text-sm",
16
+ group: "m-0 list-none p-0",
17
+ row: "flex min-h-8 cursor-pointer select-none items-center gap-1.5 rounded-md pr-2 text-fg outline-hidden hover:bg-surface-2 data-[selected]:bg-accent-soft data-[selected]:font-semibold data-[disabled]:cursor-default data-[disabled]:opacity-50",
18
+ 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",
19
+ icon: "flex shrink-0 items-center text-fg-secondary [&>svg]:h-4 [&>svg]:w-4",
20
+ label: "min-w-0 flex-1 truncate",
21
+ meta: "shrink-0 text-xs tabular-nums text-fg-secondary"
22
+ }
23
+ });
24
+ var isBranch = (node) => Boolean(node.children?.length || node.hasChildren);
25
+ function flatten(nodes, open, level = 1, parent = null, out = []) {
26
+ nodes.forEach((node, i) => {
27
+ out.push({ node, level, parent, posinset: i + 1, setsize: nodes.length });
28
+ if (open.has(node.id) && node.children) flatten(node.children, open, level + 1, node.id, out);
29
+ });
30
+ return out;
31
+ }
32
+ function TreeView({
33
+ nodes,
34
+ "aria-label": label,
35
+ expanded: expandedProp,
36
+ defaultExpanded = [],
37
+ onExpandedChange,
38
+ selected: selectedProp,
39
+ defaultSelected = null,
40
+ onSelect,
41
+ onLoadChildren,
42
+ loadingLabel = "Loading",
43
+ className
44
+ }) {
45
+ const s = treeView();
46
+ const uid = React.useId();
47
+ const [expanded, setExpanded] = useControllable(expandedProp, defaultExpanded, onExpandedChange);
48
+ const [selected, setSelected] = useControllable(selectedProp, defaultSelected);
49
+ const open = new Set(expanded);
50
+ const rows = flatten(nodes, open);
51
+ const [active, setActive] = React.useState(null);
52
+ const focusId = active && rows.some((r) => r.node.id === active) ? active : selected ?? rows[0]?.node.id ?? null;
53
+ const refs = React.useRef(/* @__PURE__ */ new Map());
54
+ const move = (id) => {
55
+ if (!id) return;
56
+ setActive(id);
57
+ refs.current.get(id)?.focus();
58
+ };
59
+ const toggle = (node, to = !open.has(node.id)) => {
60
+ if (!isBranch(node)) return;
61
+ if (to && node.hasChildren && !node.children) onLoadChildren?.(node);
62
+ setExpanded(to ? [...expanded, node.id] : expanded.filter((id) => id !== node.id));
63
+ };
64
+ const choose = (node) => {
65
+ if (node.disabled) return;
66
+ setSelected(node.id);
67
+ onSelect?.(node);
68
+ };
69
+ const onKeyDown = (event, i) => {
70
+ const row = rows[i];
71
+ const { node } = row;
72
+ const keys = {
73
+ ArrowDown: () => move(rows[i + 1]?.node.id),
74
+ ArrowUp: () => move(rows[i - 1]?.node.id),
75
+ Home: () => move(rows[0]?.node.id),
76
+ End: () => move(rows[rows.length - 1]?.node.id),
77
+ ArrowRight: () => isBranch(node) && !open.has(node.id) ? toggle(node, true) : isBranch(node) ? move(rows[i + 1]?.node.id) : void 0,
78
+ ArrowLeft: () => open.has(node.id) ? toggle(node, false) : move(row.parent ?? void 0),
79
+ Enter: () => choose(node),
80
+ " ": () => choose(node)
81
+ };
82
+ const run = keys[event.key];
83
+ if (run) {
84
+ event.preventDefault();
85
+ run();
86
+ return;
87
+ }
88
+ if (event.key.length === 1 && /\S/.test(event.key)) {
89
+ const letter = event.key.toLowerCase();
90
+ const next = [...rows.slice(i + 1), ...rows.slice(0, i)].find((r) => r.node.label.toLowerCase().startsWith(letter));
91
+ move(next?.node.id);
92
+ }
93
+ };
94
+ const render = (list, level) => list.map((node) => {
95
+ const i = rows.findIndex((r) => r.node.id === node.id);
96
+ const row = rows[i];
97
+ const branch = isBranch(node);
98
+ const isOpen = open.has(node.id);
99
+ const loading = isOpen && node.hasChildren && !node.children;
100
+ return (
101
+ // The row is the treeitem (its name is its own words, never its children's); the group of children hangs
102
+ // from it with aria-owns, in the `li` that holds both.
103
+ /* @__PURE__ */ jsxs("li", { role: "none", children: [
104
+ /* @__PURE__ */ jsxs(
105
+ "div",
106
+ {
107
+ ref: (el) => {
108
+ if (el) refs.current.set(node.id, el);
109
+ else refs.current.delete(node.id);
110
+ },
111
+ role: "treeitem",
112
+ "aria-level": level,
113
+ "aria-posinset": row.posinset,
114
+ "aria-setsize": row.setsize,
115
+ "aria-expanded": branch ? isOpen : void 0,
116
+ "aria-selected": selected === node.id,
117
+ "aria-disabled": node.disabled || void 0,
118
+ "aria-busy": loading || void 0,
119
+ "aria-owns": branch && isOpen ? `${uid}-${node.id}-group` : void 0,
120
+ tabIndex: node.id === focusId ? 0 : -1,
121
+ onKeyDown: (e) => {
122
+ if (e.target === e.currentTarget) onKeyDown(e, i);
123
+ },
124
+ onFocus: (e) => {
125
+ if (e.target === e.currentTarget) setActive(node.id);
126
+ },
127
+ className: s.row({ className: "outline-hidden focus-visible:ring-2 focus-visible:ring-ring" }),
128
+ "data-selected": selected === node.id || void 0,
129
+ "data-disabled": node.disabled || void 0,
130
+ style: { paddingLeft: `${(level - 1) * 1.25 + 0.25}rem` },
131
+ onClick: () => {
132
+ if (branch) toggle(node);
133
+ choose(node);
134
+ move(node.id);
135
+ },
136
+ children: [
137
+ /* @__PURE__ */ jsx("span", { className: s.toggle(), "aria-hidden": true, children: branch ? /* @__PURE__ */ jsx(ChevronGlyph, { direction: isOpen ? "down" : "right" }) : null }),
138
+ node.icon ? /* @__PURE__ */ jsx("span", { className: s.icon(), "aria-hidden": true, children: node.icon }) : null,
139
+ /* @__PURE__ */ jsx("span", { className: s.label(), children: node.label }),
140
+ node.meta ? /* @__PURE__ */ jsx("span", { className: s.meta(), children: node.meta }) : null
141
+ ]
142
+ }
143
+ ),
144
+ branch && isOpen ? /* @__PURE__ */ jsx("ul", { role: "group", id: `${uid}-${node.id}-group`, className: s.group(), children: loading ? /* @__PURE__ */ jsx("li", { role: "none", className: "py-1 text-xs text-fg-secondary", style: { paddingLeft: `${level * 1.25 + 1.75}rem` }, children: loadingLabel }) : render(node.children ?? [], level + 1) }) : null
145
+ ] }, node.id)
146
+ );
147
+ });
148
+ return /* @__PURE__ */ jsx("ul", { role: "tree", "aria-label": label, className: s.root({ className }), children: render(nodes, 1) });
149
+ }
150
+ export {
151
+ TreeView,
152
+ treeView
153
+ };
154
+ //# sourceMappingURL=tree-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tree-view/tree-view.tsx"],"sourcesContent":["// 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"],"mappings":"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","names":[]}