@krizaka/ui 3.20.0 → 3.22.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 (263) hide show
  1. package/README.md +1 -0
  2. package/dist/action-bar.js +4 -4
  3. package/dist/app-shell.js +1 -1
  4. package/dist/argument-card.js +4 -4
  5. package/dist/blocks.css +1 -1
  6. package/dist/button.js +3 -2
  7. package/dist/card.js +3 -3
  8. package/dist/{chunk-5MH64NIL.js → chunk-2L67YTNV.js} +2 -2
  9. package/dist/{chunk-2NB27LM7.js → chunk-3IN6TOPM.js} +4 -4
  10. package/dist/{chunk-VDR2EP6K.js → chunk-4QN5YJ3D.js} +17 -5
  11. package/dist/chunk-4QN5YJ3D.js.map +1 -0
  12. package/dist/chunk-AQSZJJAJ.js +126 -0
  13. package/dist/chunk-AQSZJJAJ.js.map +1 -0
  14. package/dist/{chunk-3GODX3D6.js → chunk-QDXV544C.js} +2 -2
  15. package/dist/chunk-QDXV544C.js.map +1 -0
  16. package/dist/chunk-R6NK6ZNY.js +1080 -0
  17. package/dist/chunk-R6NK6ZNY.js.map +1 -0
  18. package/dist/chunk-TDG7ED2W.js +1 -0
  19. package/dist/chunk-TDG7ED2W.js.map +1 -0
  20. package/dist/{chunk-LIPK4UCS.js → chunk-YCIBJ6OQ.js} +140 -209
  21. package/dist/chunk-YCIBJ6OQ.js.map +1 -0
  22. package/dist/code-block.js +17 -5
  23. package/dist/code-block.js.map +1 -1
  24. package/dist/comparison-table.d.ts +44 -0
  25. package/dist/comparison-table.js +84 -0
  26. package/dist/comparison-table.js.map +1 -0
  27. package/dist/data-table.js +19 -1066
  28. package/dist/data-table.js.map +1 -1
  29. package/dist/date-picker.js +5 -5
  30. package/dist/date-picker.js.map +1 -1
  31. package/dist/force-update-screen.d.ts +80 -0
  32. package/dist/force-update-screen.js +38 -0
  33. package/dist/force-update-screen.js.map +1 -0
  34. package/dist/genui.d.ts +219 -0
  35. package/dist/genui.js +506 -0
  36. package/dist/genui.js.map +1 -0
  37. package/dist/index.d.ts +17 -24
  38. package/dist/index.js +1 -1
  39. package/dist/maintenance-screen.d.ts +68 -0
  40. package/dist/maintenance-screen.js +35 -0
  41. package/dist/maintenance-screen.js.map +1 -0
  42. package/dist/marketing-layout.js +1 -1
  43. package/dist/marketing-layout.js.map +1 -1
  44. package/dist/media-grid.js +44 -152
  45. package/dist/media-grid.js.map +1 -1
  46. package/dist/meta-row.d.ts +54 -0
  47. package/dist/meta-row.js +35 -0
  48. package/dist/meta-row.js.map +1 -0
  49. package/dist/native.d.ts +92 -16
  50. package/dist/native.js +873 -814
  51. package/dist/native.js.map +1 -1
  52. package/dist/nav-bar.d.ts +30 -7
  53. package/dist/nav-bar.js +71 -17
  54. package/dist/nav-bar.js.map +1 -1
  55. package/dist/page-hero.js +5 -5
  56. package/dist/radio-group.js +1 -1
  57. package/dist/settings-layout.js +1 -1
  58. package/dist/settings-layout.js.map +1 -1
  59. package/dist/site-footer.js +2 -2
  60. package/dist/skip-link.js +1 -1
  61. package/dist/step-showcase.d.ts +62 -0
  62. package/dist/step-showcase.js +227 -0
  63. package/dist/step-showcase.js.map +1 -0
  64. package/dist/tabs.js +2 -2
  65. package/dist/tabs.js.map +1 -1
  66. package/dist/update-prompt.d.ts +86 -0
  67. package/dist/update-prompt.js +41 -0
  68. package/dist/update-prompt.js.map +1 -0
  69. package/dist/video-player.d.ts +1 -1
  70. package/dist/video-player.js +16 -3
  71. package/dist/video-player.js.map +1 -1
  72. package/package.json +108 -9
  73. package/registry/achievement.json +1 -1
  74. package/registry/action-bar.json +1 -1
  75. package/registry/activity-feed.json +1 -1
  76. package/registry/alert.json +1 -1
  77. package/registry/app-shell.json +1 -1
  78. package/registry/argument-card.json +1 -1
  79. package/registry/audio-player.json +1 -1
  80. package/registry/auth-layout.json +1 -1
  81. package/registry/avatar.json +1 -1
  82. package/registry/badge.json +1 -1
  83. package/registry/button.json +1 -1
  84. package/registry/card-grid.json +1 -1
  85. package/registry/card.json +1 -1
  86. package/registry/catalogue-page.json +1 -1
  87. package/registry/changelog-page.json +1 -1
  88. package/registry/chat.json +1 -1
  89. package/registry/checkbox.json +1 -1
  90. package/registry/chip-link.json +1 -1
  91. package/registry/chip.json +1 -1
  92. package/registry/choice-grid.json +1 -1
  93. package/registry/code-block.json +1 -1
  94. package/registry/combobox.json +1 -1
  95. package/registry/command.json +1 -1
  96. package/registry/comparison-table.json +207 -0
  97. package/registry/component-page.json +1 -1
  98. package/registry/confirm-button.json +1 -1
  99. package/registry/contact-page.json +1 -1
  100. package/registry/continue-prompt.json +1 -1
  101. package/registry/countdown.json +1 -1
  102. package/registry/cta-panel.json +1 -1
  103. package/registry/dashboard-layout.json +1 -1
  104. package/registry/data-table.json +1 -1
  105. package/registry/date-picker.json +3 -3
  106. package/registry/decision-list.json +1 -1
  107. package/registry/description-list.json +1 -1
  108. package/registry/detail-layout.json +1 -1
  109. package/registry/dialog.json +1 -1
  110. package/registry/docs-article-page.json +1 -1
  111. package/registry/docs-hub-page.json +1 -1
  112. package/registry/docs-layout.json +1 -1
  113. package/registry/document-viewer.json +1 -1
  114. package/registry/dropdown-menu.json +1 -1
  115. package/registry/empty-state.json +1 -1
  116. package/registry/error-page.json +1 -1
  117. package/registry/examples/comparison-table/versus.d.ts +4 -0
  118. package/registry/examples/comparison-table/versus.js +28 -0
  119. package/registry/examples/comparison-table/versus.tsx +20 -0
  120. package/registry/examples/dialog/native/sheet.dark.png +0 -0
  121. package/registry/examples/dialog/native/sheet.light.png +0 -0
  122. package/registry/examples/force-update-screen/default.d.ts +4 -0
  123. package/registry/examples/force-update-screen/default.js +25 -0
  124. package/registry/examples/force-update-screen/default.tsx +19 -0
  125. package/registry/examples/force-update-screen/native/default.d.ts +4 -0
  126. package/registry/examples/force-update-screen/native/default.dark.png +0 -0
  127. package/registry/examples/force-update-screen/native/default.js +24 -0
  128. package/registry/examples/force-update-screen/native/default.light.png +0 -0
  129. package/registry/examples/force-update-screen/native/default.tsx +18 -0
  130. package/registry/examples/genui/streaming.d.ts +4 -0
  131. package/registry/examples/genui/streaming.js +18 -0
  132. package/registry/examples/genui/streaming.tsx +14 -0
  133. package/registry/examples/genui/table.d.ts +4 -0
  134. package/registry/examples/genui/table.js +19 -0
  135. package/registry/examples/genui/table.tsx +14 -0
  136. package/registry/examples/maintenance-screen/default.d.ts +4 -0
  137. package/registry/examples/maintenance-screen/default.js +22 -0
  138. package/registry/examples/maintenance-screen/default.tsx +16 -0
  139. package/registry/examples/maintenance-screen/native/default.d.ts +4 -0
  140. package/registry/examples/maintenance-screen/native/default.dark.png +0 -0
  141. package/registry/examples/maintenance-screen/native/default.js +21 -0
  142. package/registry/examples/maintenance-screen/native/default.light.png +0 -0
  143. package/registry/examples/maintenance-screen/native/default.tsx +15 -0
  144. package/registry/examples/meta-row/native/video.d.ts +4 -0
  145. package/registry/examples/meta-row/native/video.dark.png +0 -0
  146. package/registry/examples/meta-row/native/video.js +11 -0
  147. package/registry/examples/meta-row/native/video.light.png +0 -0
  148. package/registry/examples/meta-row/native/video.tsx +5 -0
  149. package/registry/examples/meta-row/status.d.ts +4 -0
  150. package/registry/examples/meta-row/status.js +12 -0
  151. package/registry/examples/meta-row/status.tsx +7 -0
  152. package/registry/examples/meta-row/video.d.ts +4 -0
  153. package/registry/examples/meta-row/video.js +12 -0
  154. package/registry/examples/meta-row/video.tsx +7 -0
  155. package/registry/examples/nav-bar/family-product.js +16 -13
  156. package/registry/examples/nav-bar/family-product.tsx +19 -19
  157. package/registry/examples/step-showcase/desktop.d.ts +4 -0
  158. package/registry/examples/step-showcase/desktop.js +24 -0
  159. package/registry/examples/step-showcase/desktop.tsx +19 -0
  160. package/registry/examples/step-showcase/phone.d.ts +4 -0
  161. package/registry/examples/step-showcase/phone.js +24 -0
  162. package/registry/examples/step-showcase/phone.tsx +19 -0
  163. package/registry/examples/update-prompt/default.d.ts +4 -0
  164. package/registry/examples/update-prompt/default.js +24 -0
  165. package/registry/examples/update-prompt/default.tsx +18 -0
  166. package/registry/examples/update-prompt/native/default.d.ts +4 -0
  167. package/registry/examples/update-prompt/native/default.dark.png +0 -0
  168. package/registry/examples/update-prompt/native/default.js +23 -0
  169. package/registry/examples/update-prompt/native/default.light.png +0 -0
  170. package/registry/examples/update-prompt/native/default.tsx +17 -0
  171. package/registry/field.json +1 -1
  172. package/registry/file-upload.json +1 -1
  173. package/registry/filter-bar.json +1 -1
  174. package/registry/force-update-screen.json +323 -0
  175. package/registry/form.json +1 -1
  176. package/registry/gallery-page.json +1 -1
  177. package/registry/genui.json +409 -0
  178. package/registry/glow-card.json +1 -1
  179. package/registry/goal-gauge.json +1 -1
  180. package/registry/how-it-works-page.json +1 -1
  181. package/registry/image-cropper.json +1 -1
  182. package/registry/index.json +223 -4
  183. package/registry/iso.json +1 -1
  184. package/registry/kanban.json +1 -1
  185. package/registry/kbd.json +1 -1
  186. package/registry/landing-page.json +1 -1
  187. package/registry/landscape.json +1 -1
  188. package/registry/legal-page.json +1 -1
  189. package/registry/link-card.json +1 -1
  190. package/registry/list.json +1 -1
  191. package/registry/loader.json +1 -1
  192. package/registry/longform-page.json +1 -1
  193. package/registry/maintenance-screen.json +259 -0
  194. package/registry/map.json +2 -2
  195. package/registry/markdown.json +1 -1
  196. package/registry/marketing-layout.json +1 -1
  197. package/registry/marquee.json +1 -1
  198. package/registry/mascot-quote.json +1 -1
  199. package/registry/mascot-state.json +1 -1
  200. package/registry/mascots.json +1 -1
  201. package/registry/match-dialog.json +1 -1
  202. package/registry/media-capture.json +1 -1
  203. package/registry/media-grid.json +2 -2
  204. package/registry/meta-row.json +215 -0
  205. package/registry/meter.json +1 -1
  206. package/registry/nav-bar.json +58 -25
  207. package/registry/number-ticker.json +1 -1
  208. package/registry/page-header.json +1 -1
  209. package/registry/page-hero.json +1 -1
  210. package/registry/page.json +1 -1
  211. package/registry/pagination.json +1 -1
  212. package/registry/photo-grid.json +1 -1
  213. package/registry/pointer-light.json +1 -1
  214. package/registry/popover.json +1 -1
  215. package/registry/pricing-page.json +1 -1
  216. package/registry/product-page.json +1 -1
  217. package/registry/profile-card.json +1 -1
  218. package/registry/progress.json +1 -1
  219. package/registry/promise-card.json +1 -1
  220. package/registry/radio-group.json +2 -2
  221. package/registry/recipes.json +1 -1
  222. package/registry/scroll-stage.json +1 -1
  223. package/registry/search-field.json +1 -1
  224. package/registry/section-backdrop.json +1 -1
  225. package/registry/separator.json +1 -1
  226. package/registry/settings-layout.json +2 -2
  227. package/registry/showcase.json +1 -1
  228. package/registry/site-footer.json +13 -13
  229. package/registry/sites.json +1 -1
  230. package/registry/skeleton.json +1 -1
  231. package/registry/skip-link.json +2 -2
  232. package/registry/slider.json +1 -1
  233. package/registry/slot.json +1 -1
  234. package/registry/spinner.json +1 -1
  235. package/registry/split-view.json +1 -1
  236. package/registry/stage-banner.json +1 -1
  237. package/registry/stat.json +1 -1
  238. package/registry/status-page.json +1 -1
  239. package/registry/step-progress.json +1 -1
  240. package/registry/step-showcase.json +296 -0
  241. package/registry/stepper.json +1 -1
  242. package/registry/swipe-deck.json +1 -1
  243. package/registry/switch.json +1 -1
  244. package/registry/tabs.json +3 -3
  245. package/registry/tag-input.json +1 -1
  246. package/registry/tag-selector.json +1 -1
  247. package/registry/terminal-replay.json +1 -1
  248. package/registry/theme.json +1 -1
  249. package/registry/toast.json +1 -1
  250. package/registry/toc.json +1 -1
  251. package/registry/tooltip.json +1 -1
  252. package/registry/tree-view.json +1 -1
  253. package/registry/update-prompt.json +316 -0
  254. package/registry/verified-badge.json +1 -1
  255. package/registry/vertical-video.json +1 -1
  256. package/registry/video-player.json +4 -4
  257. package/registry/video-trimmer.json +1 -1
  258. package/registry/virtual.json +1 -1
  259. package/dist/chunk-3GODX3D6.js.map +0 -1
  260. package/dist/chunk-LIPK4UCS.js.map +0 -1
  261. package/dist/chunk-VDR2EP6K.js.map +0 -1
  262. /package/dist/{chunk-5MH64NIL.js.map → chunk-2L67YTNV.js.map} +0 -0
  263. /package/dist/{chunk-2NB27LM7.js.map → chunk-3IN6TOPM.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -15,18 +15,17 @@ interface MarkProps {
15
15
  }
16
16
 
17
17
  /**
18
- * The Akinaza mark, "the open shop": a filled awning with the Krizaka cut at its corner, scalloped, its stripes in
19
- * light; under it the shop front, two windows and the open door — a warm light that breathes. In the Akinaza gradient
20
- * (forest → copper, the brand's mark gradient of @krizaka/tokens, the same in dark and light); one node, a coin, rides
21
- * the dashed orbit. The family's grammar (orbit, ring, bold emblem, bright core). Below 48 px it crops to the emblem.
18
+ * The Akinaza mark, "the cut log": a log seen end-on in forest green, its year rings in light, cut at 45° by the beaver
19
+ * (the Krizaka chamfer) with the fresh face in copper, and a copper heart that breathes — a shop built ring by ring.
20
+ * One node, a coin, rides the dashed orbit. Below 48 px it crops to the emblem.
22
21
  */
23
22
  declare function AkinazaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
24
23
 
25
24
  /**
26
- * The Kachizaka mark, "the sealed cup": a filled trophy whose rim wears the Krizaka cut, two handles, a stem and a
27
- * base, in the Kachizaka gradient (cobalt → gold, the brand's mark gradient of @krizaka/tokens, the same in dark and
28
- * light); on the bowl a star in light — the seal of the rules, locked at kick-off — breathes; one node, the ball, rides
29
- * the dashed orbit. The family's grammar (orbit, ring, bold emblem, bright core). Below 48 px it crops to the emblem.
25
+ * The Kachizaka mark, "the podium": three steps cut at their outer corners, the winner in gold and the others in cobalt
26
+ * (the brand's two colours, kept apart), under a gold diamond — the family's lit node — that breathes: a friendly
27
+ * leaderboard where only points change hands. One node, the ball, rides the dashed orbit. Below 48 px it crops to the
28
+ * emblem.
30
29
  */
31
30
  declare function KachizakaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
32
31
 
@@ -57,32 +56,26 @@ declare function ProductLogo({ id, ...props }: MarkProps & {
57
56
  }): React.JSX.Element;
58
57
 
59
58
  /**
60
- * The Yasakia mark: two voices — two solid speech bubbles that overlap, the left a shade deeper — in the Yasakia
61
- * gradient (emerald → turquoise, the brand's mark gradient of @krizaka/tokens, the same in dark and light). Where they
62
- * overlap, what the two share, is the bright core: a lens lit from above that breathes. The pair, two nodes on the
63
- * dashed orbit, turns slowly around it — the family's grammar (orbit, ring, bold emblem, bright core). Below 48 px it
64
- * crops to the emblem.
59
+ * The Yasakia mark, "one conversation": one speech bubble with a tail on each side (turned 180°, never mirrored, so it
60
+ * can never read as a face) in the Yasakia gradient (emerald → turquoise, the same in dark and light), and the spark
61
+ * inside it — the family's lit node — that breathes: talk first, both ways. One node rides the dashed orbit. Below 48 px
62
+ * it crops to the emblem.
65
63
  */
66
64
  declare function YasakiaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
67
65
  /** @deprecated Yazakia was renamed Yasakia (2026-10): use `YasakiaLogo`. Kept for one minor version. */
68
66
  declare const YazakiaLogo: typeof YasakiaLogo;
69
67
 
70
68
  /**
71
- * The Yomizaka mark, "the reading": a filled page with the Krizaka cut at its corner, three lines of text in light, and
72
- * a lens — the eye that reads — resting on its lower half, its handle running out of the page. Page and lens in the
73
- * Yomizaka gradient (ink → indigo, the brand's mark gradient of @krizaka/tokens, the same in dark and light); the
74
- * lens' core is a pale indigo light that breathes; a line of light scans the page from top to bottom; one node, a
75
- * page, rides the dashed orbit. The family's grammar (orbit, ring, bold emblem, bright core). Below 48 px it crops to
76
- * the emblem.
69
+ * The Yomizaka mark, "the watch": the owl — two lenses at the family stroke under one calm brow, its pupils glancing
70
+ * down the line it reads — in the Yomizaka gradient (ink → indigo, the same in dark and light). The pupils are the lit
71
+ * cores and breathe; one node, a page, rides the dashed orbit. Below 48 px it crops to the emblem.
77
72
  */
78
73
  declare function YomizakaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
79
74
 
80
75
  /**
81
- * The Yororis mark, "the hold": a "Y" whose arms are two filled leaves — open hands — rising from one stem and cupping
82
- * a warm core that breathes: held, given room, listened to. Leaves in the Yororis gradient (sand → sage, the brand's
83
- * mark gradient of @krizaka/tokens, the same in dark and light), a vein of light along each, the core in a warm sand
84
- * light; the moment, one node on the dashed orbit, comes round slowly. The family's grammar (orbit, ring, bold emblem,
85
- * bright core) with the slowest breath of the family. Below 48 px it crops to the emblem.
76
+ * The Yororis mark, "held": two open hands, two sage arcs of one circle, cup a warm sand core without closing on it —
77
+ * held, given room, free to go. The core breathes, the slowest breath of the family; one node, the moment, rides the
78
+ * dashed orbit. Below 48 px it crops to the emblem.
86
79
  */
87
80
  declare function YororisLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
88
81
 
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  YazakiaLogo,
15
15
  YomizakaLogo,
16
16
  YororisLogo
17
- } from "./chunk-LIPK4UCS.js";
17
+ } from "./chunk-YCIBJ6OQ.js";
18
18
  import {
19
19
  cx
20
20
  } from "./chunk-6ISW63JI.js";
@@ -0,0 +1,68 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const maintenanceScreen: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ mark?: tailwind_variants.ClassValue;
8
+ title?: tailwind_variants.ClassValue;
9
+ root?: tailwind_variants.ClassValue;
10
+ message?: tailwind_variants.ClassValue;
11
+ actions?: tailwind_variants.ClassValue;
12
+ };
13
+ };
14
+ } | {
15
+ [x: string]: {
16
+ [x: string]: tailwind_variants.ClassValue | {
17
+ mark?: tailwind_variants.ClassValue;
18
+ title?: tailwind_variants.ClassValue;
19
+ root?: tailwind_variants.ClassValue;
20
+ message?: tailwind_variants.ClassValue;
21
+ actions?: tailwind_variants.ClassValue;
22
+ };
23
+ };
24
+ } | {}, {
25
+ root: string;
26
+ mark: string;
27
+ title: string;
28
+ message: string;
29
+ actions: string;
30
+ }, undefined, {
31
+ [key: string]: {
32
+ [key: string]: tailwind_variants.ClassValue | {
33
+ mark?: tailwind_variants.ClassValue;
34
+ title?: tailwind_variants.ClassValue;
35
+ root?: tailwind_variants.ClassValue;
36
+ message?: tailwind_variants.ClassValue;
37
+ actions?: tailwind_variants.ClassValue;
38
+ };
39
+ };
40
+ } | {}, {
41
+ root: string;
42
+ mark: string;
43
+ title: string;
44
+ message: string;
45
+ actions: string;
46
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
47
+ root: string;
48
+ mark: string;
49
+ title: string;
50
+ message: string;
51
+ actions: string;
52
+ }>>;
53
+ type MaintenanceScreenProps = Omit<React.ComponentProps<"main">, "title"> & {
54
+ /** The headline (“Back in a few minutes”). */
55
+ title: React.ReactNode;
56
+ /** What is happening — the backend's localized maintenance `message`. */
57
+ message?: React.ReactNode;
58
+ /** The product's mark or mascot (decorative). */
59
+ mark?: React.ReactNode;
60
+ /** The button that checks again (“Try again”). */
61
+ retryLabel?: string;
62
+ /** Checks the backend again. */
63
+ onRetry?: () => void;
64
+ };
65
+ /** The maintenance screen: announced politely, with one way to check again. */
66
+ declare function MaintenanceScreen({ title, message, mark, retryLabel, onRetry, className, ...props }: MaintenanceScreenProps): React.JSX.Element;
67
+
68
+ export { MaintenanceScreen, type MaintenanceScreenProps, maintenanceScreen };
@@ -0,0 +1,35 @@
1
+ import "./chunk-TDG7ED2W.js";
2
+ import {
3
+ Button
4
+ } from "./chunk-3IN6TOPM.js";
5
+ import "./chunk-43PTCDTL.js";
6
+ import "./chunk-2VNYHG4E.js";
7
+
8
+ // src/maintenance-screen/maintenance-screen.tsx
9
+ import { tv } from "tailwind-variants";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ var maintenanceScreen = tv({
12
+ slots: {
13
+ root: "mx-auto flex min-h-dvh w-full max-w-md flex-col items-center justify-center gap-4 px-6 py-12 text-center text-fg",
14
+ mark: "flex h-24 w-24 items-center justify-center [&>svg]:h-24 [&>svg]:w-24",
15
+ title: "text-2xl font-semibold text-fg",
16
+ message: "text-fg-secondary",
17
+ actions: "mt-2 flex w-full flex-col gap-2"
18
+ }
19
+ });
20
+ function MaintenanceScreen({ title, message, mark, retryLabel, onRetry, className, ...props }) {
21
+ const s = maintenanceScreen();
22
+ return /* @__PURE__ */ jsxs("main", { "data-kind": "maintenance", className: s.root({ className }), ...props, children: [
23
+ mark && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: s.mark(), children: mark }),
24
+ /* @__PURE__ */ jsxs("div", { role: "status", className: "flex flex-col items-center gap-4", children: [
25
+ /* @__PURE__ */ jsx("h1", { className: s.title(), children: title }),
26
+ message && /* @__PURE__ */ jsx("p", { className: s.message(), children: message })
27
+ ] }),
28
+ retryLabel && onRetry && /* @__PURE__ */ jsx("div", { className: s.actions(), children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onRetry, children: retryLabel }) })
29
+ ] });
30
+ }
31
+ export {
32
+ MaintenanceScreen,
33
+ maintenanceScreen
34
+ };
35
+ //# sourceMappingURL=maintenance-screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/maintenance-screen/maintenance-screen.tsx"],"sourcesContent":["// Server-safe. The service is down on purpose (maintenance on, from the backend's parameters): say so, say when to\n// come back, and let the person check again. Replaces the app, like the forced update.\nimport { Button } from \"@krizaka/ui/button\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const maintenanceScreen = tv({\n slots: {\n root: \"mx-auto flex min-h-dvh w-full max-w-md flex-col items-center justify-center gap-4 px-6 py-12 text-center text-fg\",\n mark: \"flex h-24 w-24 items-center justify-center [&>svg]:h-24 [&>svg]:w-24\",\n title: \"text-2xl font-semibold text-fg\",\n message: \"text-fg-secondary\",\n actions: \"mt-2 flex w-full flex-col gap-2\",\n },\n});\n\nexport type MaintenanceScreenProps = Omit<React.ComponentProps<\"main\">, \"title\"> & {\n /** The headline (“Back in a few minutes”). */\n title: React.ReactNode;\n /** What is happening — the backend's localized maintenance `message`. */\n message?: React.ReactNode;\n /** The product's mark or mascot (decorative). */\n mark?: React.ReactNode;\n /** The button that checks again (“Try again”). */\n retryLabel?: string;\n /** Checks the backend again. */\n onRetry?: () => void;\n};\n\n/** The maintenance screen: announced politely, with one way to check again. */\nexport function MaintenanceScreen({ title, message, mark, retryLabel, onRetry, className, ...props }: MaintenanceScreenProps) {\n const s = maintenanceScreen();\n return (\n <main data-kind=\"maintenance\" className={s.root({ className })} {...props}>\n {mark && (\n <div aria-hidden className={s.mark()}>\n {mark}\n </div>\n )}\n <div role=\"status\" className=\"flex flex-col items-center gap-4\">\n <h1 className={s.title()}>{title}</h1>\n {message && <p className={s.message()}>{message}</p>}\n </div>\n {retryLabel && onRetry && (\n <div className={s.actions()}>\n <Button variant=\"secondary\" onClick={onRetry}>\n {retryLabel}\n </Button>\n </div>\n )}\n </main>\n );\n}\n"],"mappings":";;;;;;;;AAIA,SAAS,UAAU;AA+BX,cAIF,YAJE;AA7BD,IAAM,oBAAoB,GAAG;AAAA,EAClC,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF,CAAC;AAgBM,SAAS,kBAAkB,EAAE,OAAO,SAAS,MAAM,YAAY,SAAS,WAAW,GAAG,MAAM,GAA2B;AAC5H,QAAM,IAAI,kBAAkB;AAC5B,SACE,qBAAC,UAAK,aAAU,eAAc,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACjE;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,qBAAC,SAAI,MAAK,UAAS,WAAU,oCAC3B;AAAA,0BAAC,QAAG,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,MAChC,WAAW,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,mBAAQ;AAAA,OAClD;AAAA,IACC,cAAc,WACb,oBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB,8BAAC,UAAO,SAAQ,aAAY,SAAS,SAClC,sBACH,GACF;AAAA,KAEJ;AAEJ;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import { tv } from "tailwind-variants";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  var skipLink = tv({
5
- base: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-full focus:bg-surface-1 focus:px-4 focus:py-2 focus:text-sm focus:font-semibold focus:text-fg focus:no-underline focus:shadow-lg focus:outline-hidden focus:ring-2 focus:ring-ring"
5
+ base: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-full focus:bg-surface-1 focus:px-4 focus:py-2 focus:text-sm focus:font-semibold focus:text-fg focus:no-underline focus:shadow-lg focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
6
6
  });
7
7
  function SkipLink({ href = "#content", className, onClick, children, ...props }) {
8
8
  const handleClick = (event) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/skip-link/skip-link.tsx","../src/marketing-layout/marketing-layout.tsx"],"sourcesContent":["// Client (it moves focus). WCAG 2.4.1 Bypass Blocks: the first tab stop of a page, a link that skips the navigation and\n// lands on the content. Visually hidden until focused, then a pill above everything in the brand ring. The label is\n// passed translated; the target needs an `id` (and is made focusable, so focus really moves, router or not).\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const skipLink = tv({\n base:\n \"sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-full focus:bg-surface-1 focus:px-4 focus:py-2 \" +\n \"focus:text-sm focus:font-semibold focus:text-fg focus:no-underline focus:shadow-lg focus:outline-hidden focus:ring-2 focus:ring-ring\",\n});\n\nexport type SkipLinkProps = Omit<React.ComponentProps<\"a\">, \"href\"> & {\n /**\n * The content to land on: `#` and its `id`. The element becomes focusable (`tabindex=\"-1\"`) when it is not.\n * @default \"#content\"\n */\n href?: `#${string}`;\n};\n\n/** A \"skip to content\" link: the first tab stop, hidden until focused; Enter moves focus to the target. */\nexport function SkipLink({ href = \"#content\", className, onClick, children, ...props }: SkipLinkProps) {\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n const target = document.getElementById(decodeURIComponent(href.slice(1)));\n if (!target) return;\n if (!target.hasAttribute(\"tabindex\") && !target.matches(\"a[href], button, input, select, textarea, [contenteditable]\")) target.setAttribute(\"tabindex\", \"-1\");\n target.focus();\n };\n return (\n <a href={href} className={skipLink({ className })} onClick={handleClick} {...props}>\n {children}\n </a>\n );\n}\n","// Server-safe. The page of a site (krizaka.com, a product's public pages): a link to skip to the content, the site's\n// bar, the page — its PageHero and Sections (@krizaka/ui/page) — and the footer. The bar floats over the hero\n// (`--kz-hero-top` clears it); everything shares the page frame (`--kz-page-max`, `--kz-page-gutter`).\nimport { SkipLink } from \"@krizaka/ui/skip-link\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const marketingLayout = tv({\n slots: {\n root: \"flex min-h-dvh w-full flex-col bg-surface-0 text-fg\",\n header: \"fixed inset-x-0 top-3 z-50 px-(--kz-page-gutter,16px) pointer-events-none *:pointer-events-auto\",\n main: \"flex-1 outline-hidden\",\n },\n});\nconst s = marketingLayout();\n\nexport type MarketingLayoutProps = React.ComponentProps<\"div\"> & {\n /** The site's bar (a floating NavBar of @krizaka/ui/nav-bar). */\n header: React.ReactNode;\n /** The site's footer. */\n footer?: React.ReactNode;\n /** The words of the link that skips to the content (`Skip to content`). */\n skipLabel: string;\n /** The page: a PageHero, then Sections. */\n children: React.ReactNode;\n};\n\n/** A site's page: skip link, floating bar, the page, the footer. */\nexport function MarketingLayout({ header, footer, skipLabel, className, children, ...props }: MarketingLayoutProps) {\n return (\n <div className={s.root({ className })} {...props}>\n <SkipLink>{skipLabel}</SkipLink>\n <div className={s.header()}>{header}</div>\n <main id=\"content\" tabIndex={-1} className={s.main()}>\n {children}\n </main>\n {footer}\n </div>\n );\n}\n"],"mappings":";AAIA,SAAS,UAAU;AA2Bf;AAzBG,IAAM,WAAW,GAAG;AAAA,EACzB,MACE;AAEJ,CAAC;AAWM,SAAS,SAAS,EAAE,OAAO,YAAY,WAAW,SAAS,UAAU,GAAG,MAAM,GAAkB;AACrG,QAAM,cAAc,CAAC,UAA+C;AAClE,cAAU,KAAK;AACf,QAAI,MAAM,iBAAkB;AAC5B,UAAM,SAAS,SAAS,eAAe,mBAAmB,KAAK,MAAM,CAAC,CAAC,CAAC;AACxE,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,OAAO,aAAa,UAAU,KAAK,CAAC,OAAO,QAAQ,6DAA6D,EAAG,QAAO,aAAa,YAAY,IAAI;AAC5J,WAAO,MAAM;AAAA,EACf;AACA,SACE,oBAAC,OAAE,MAAY,WAAW,SAAS,EAAE,UAAU,CAAC,GAAG,SAAS,aAAc,GAAG,OAC1E,UACH;AAEJ;;;AC9BA,SAAS,MAAAA,WAAU;AAyBf,SACE,OAAAC,MADF;AAvBG,IAAM,kBAAkBD,IAAG;AAAA,EAChC,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AACF,CAAC;AACD,IAAM,IAAI,gBAAgB;AAcnB,SAAS,gBAAgB,EAAE,QAAQ,QAAQ,WAAW,WAAW,UAAU,GAAG,MAAM,GAAyB;AAClH,SACE,qBAAC,SAAI,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACzC;AAAA,oBAAAC,KAAC,YAAU,qBAAU;AAAA,IACrB,gBAAAA,KAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,IACpC,gBAAAA,KAAC,UAAK,IAAG,WAAU,UAAU,IAAI,WAAW,EAAE,KAAK,GAChD,UACH;AAAA,IACC;AAAA,KACH;AAEJ;","names":["tv","jsx"]}
1
+ {"version":3,"sources":["../src/skip-link/skip-link.tsx","../src/marketing-layout/marketing-layout.tsx"],"sourcesContent":["// Client (it moves focus). WCAG 2.4.1 Bypass Blocks: the first tab stop of a page, a link that skips the navigation and\n// lands on the content. Visually hidden until focused, then a pill above everything in the brand ring. The label is\n// passed translated; the target needs an `id` (and is made focusable, so focus really moves, router or not).\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const skipLink = tv({\n base:\n \"sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-full focus:bg-surface-1 focus:px-4 focus:py-2 \" +\n \"focus:text-sm focus:font-semibold focus:text-fg focus:no-underline focus:shadow-lg focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n});\n\nexport type SkipLinkProps = Omit<React.ComponentProps<\"a\">, \"href\"> & {\n /**\n * The content to land on: `#` and its `id`. The element becomes focusable (`tabindex=\"-1\"`) when it is not.\n * @default \"#content\"\n */\n href?: `#${string}`;\n};\n\n/** A \"skip to content\" link: the first tab stop, hidden until focused; Enter moves focus to the target. */\nexport function SkipLink({ href = \"#content\", className, onClick, children, ...props }: SkipLinkProps) {\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n const target = document.getElementById(decodeURIComponent(href.slice(1)));\n if (!target) return;\n if (!target.hasAttribute(\"tabindex\") && !target.matches(\"a[href], button, input, select, textarea, [contenteditable]\")) target.setAttribute(\"tabindex\", \"-1\");\n target.focus();\n };\n return (\n <a href={href} className={skipLink({ className })} onClick={handleClick} {...props}>\n {children}\n </a>\n );\n}\n","// Server-safe. The page of a site (krizaka.com, a product's public pages): a link to skip to the content, the site's\n// bar, the page — its PageHero and Sections (@krizaka/ui/page) — and the footer. The bar floats over the hero\n// (`--kz-hero-top` clears it); everything shares the page frame (`--kz-page-max`, `--kz-page-gutter`).\nimport { SkipLink } from \"@krizaka/ui/skip-link\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const marketingLayout = tv({\n slots: {\n root: \"flex min-h-dvh w-full flex-col bg-surface-0 text-fg\",\n header: \"fixed inset-x-0 top-3 z-50 px-(--kz-page-gutter,16px) pointer-events-none *:pointer-events-auto\",\n main: \"flex-1 outline-hidden\",\n },\n});\nconst s = marketingLayout();\n\nexport type MarketingLayoutProps = React.ComponentProps<\"div\"> & {\n /** The site's bar (a floating NavBar of @krizaka/ui/nav-bar). */\n header: React.ReactNode;\n /** The site's footer. */\n footer?: React.ReactNode;\n /** The words of the link that skips to the content (`Skip to content`). */\n skipLabel: string;\n /** The page: a PageHero, then Sections. */\n children: React.ReactNode;\n};\n\n/** A site's page: skip link, floating bar, the page, the footer. */\nexport function MarketingLayout({ header, footer, skipLabel, className, children, ...props }: MarketingLayoutProps) {\n return (\n <div className={s.root({ className })} {...props}>\n <SkipLink>{skipLabel}</SkipLink>\n <div className={s.header()}>{header}</div>\n <main id=\"content\" tabIndex={-1} className={s.main()}>\n {children}\n </main>\n {footer}\n </div>\n );\n}\n"],"mappings":";AAIA,SAAS,UAAU;AA2Bf;AAzBG,IAAM,WAAW,GAAG;AAAA,EACzB,MACE;AAEJ,CAAC;AAWM,SAAS,SAAS,EAAE,OAAO,YAAY,WAAW,SAAS,UAAU,GAAG,MAAM,GAAkB;AACrG,QAAM,cAAc,CAAC,UAA+C;AAClE,cAAU,KAAK;AACf,QAAI,MAAM,iBAAkB;AAC5B,UAAM,SAAS,SAAS,eAAe,mBAAmB,KAAK,MAAM,CAAC,CAAC,CAAC;AACxE,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,OAAO,aAAa,UAAU,KAAK,CAAC,OAAO,QAAQ,6DAA6D,EAAG,QAAO,aAAa,YAAY,IAAI;AAC5J,WAAO,MAAM;AAAA,EACf;AACA,SACE,oBAAC,OAAE,MAAY,WAAW,SAAS,EAAE,UAAU,CAAC,GAAG,SAAS,aAAc,GAAG,OAC1E,UACH;AAEJ;;;AC9BA,SAAS,MAAAA,WAAU;AAyBf,SACE,OAAAC,MADF;AAvBG,IAAM,kBAAkBD,IAAG;AAAA,EAChC,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AACF,CAAC;AACD,IAAM,IAAI,gBAAgB;AAcnB,SAAS,gBAAgB,EAAE,QAAQ,QAAQ,WAAW,WAAW,UAAU,GAAG,MAAM,GAAyB;AAClH,SACE,qBAAC,SAAI,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACzC;AAAA,oBAAAC,KAAC,YAAU,qBAAU;AAAA,IACrB,gBAAAA,KAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,IACpC,gBAAAA,KAAC,UAAK,IAAG,WAAU,UAAU,IAAI,WAAW,EAAE,KAAK,GAChD,UACH;AAAA,IACC;AAAA,KACH;AAEJ;","names":["tv","jsx"]}
@@ -3,14 +3,16 @@ import "./chunk-NPF3OHE2.js";
3
3
  import {
4
4
  Avatar
5
5
  } from "./chunk-KB7OLYIJ.js";
6
+ import {
7
+ Card,
8
+ Skeleton
9
+ } from "./chunk-AQSZJJAJ.js";
6
10
  import "./chunk-JXLDUDTD.js";
7
11
  import {
8
12
  Button,
9
13
  LoaderGlyph
10
14
  } from "./chunk-3BC4XQ6C.js";
11
- import {
12
- defineRecipe
13
- } from "./chunk-D3T54RSL.js";
15
+ import "./chunk-D3T54RSL.js";
14
16
  import {
15
17
  cn
16
18
  } from "./chunk-2FRWNSRO.js";
@@ -113,7 +115,7 @@ function ShortsShelf({ label, title, items, getId, renderItem, seeAll, previousL
113
115
  onScroll: measure,
114
116
  tabIndex: 0,
115
117
  "aria-labelledby": headingId,
116
- className: "m-0 flex list-none snap-x snap-mandatory items-stretch gap-3 overflow-x-auto overscroll-x-contain p-0 pb-2 [scrollbar-width:none] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&::-webkit-scrollbar]:hidden",
118
+ className: "m-0 flex list-none snap-x snap-mandatory items-stretch gap-3 overflow-x-auto overflow-y-hidden overscroll-x-contain p-0 pt-1 -mt-1 pb-2 [scrollbar-width:none] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&::-webkit-scrollbar]:hidden",
117
119
  children: items.map((item, i) => /* @__PURE__ */ jsx4("li", { className: "w-[9.5rem] shrink-0 snap-start sm:w-44", children: renderItem(item, i) }, getId(item)))
118
120
  }
119
121
  )
@@ -142,102 +144,6 @@ function MediaGrid({ items, getId, orientationOf, renderItem, mode = "split", fr
142
144
  // src/media-grid/video-card.tsx
143
145
  import * as React3 from "react";
144
146
 
145
- // src/card/card.tsx
146
- import { Slot } from "radix-ui";
147
- import { tv as tv2 } from "tailwind-variants";
148
-
149
- // src/card/recipe.ts
150
- var cardRecipe = defineRecipe({
151
- slots: {
152
- root: "group relative flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
153
- media: "relative overflow-hidden bg-media",
154
- image: "h-full w-full object-cover transition-transform duration-500 motion-safe:group-hover:scale-105",
155
- fallback: "flex h-full w-full items-center justify-center bg-linear-to-br from-accent/15 via-media to-accent-2/15 text-accent/60",
156
- overlay: "absolute z-10 flex items-center gap-1.5",
157
- body: "relative flex flex-1 flex-col gap-3",
158
- title: "line-clamp-1 text-sm font-semibold text-fg transition-colors group-hover:text-fg-accent",
159
- description: "line-clamp-2 text-xs text-fg-secondary",
160
- stat: "min-w-0",
161
- statLabel: "text-[10px] font-semibold uppercase tracking-wider text-fg-secondary",
162
- statValue: "font-display text-xl font-black tabular-nums text-fg",
163
- footer: "relative mt-auto flex items-center gap-2 border-t border-border-subtle pt-3 text-xs text-fg-secondary"
164
- },
165
- variants: {
166
- radius: { md: { root: "rounded-md" }, lg: { root: "rounded-lg" }, xl: { root: "rounded-xl" } },
167
- tone: { default: {}, elevated: { root: "bg-surface-2 shadow-md" }, glass: { root: "bg-surface-1/70 backdrop-blur-md" } },
168
- interactive: { true: { root: "kz-spotlight kz-lift hover:border-accent/50" } },
169
- padding: { none: { body: "p-0" }, sm: { body: "p-3" }, md: { body: "p-4" }, lg: { body: "p-6" } }
170
- },
171
- defaultVariants: { radius: "xl", tone: "default", padding: "md" }
172
- });
173
-
174
- // src/card/card.tsx
175
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
176
- var card = tv2(cardRecipe);
177
- var slots = card();
178
- function CardRoot({ asChild, reveal, radius, tone, interactive, className, style, ...props }) {
179
- const Comp = asChild ? Slot.Root : "div";
180
- const revealStyle = reveal === void 0 ? style : { ...style, "--kz-delay": `${Math.min(Math.max(reveal, 0), 8) * 50}ms` };
181
- return /* @__PURE__ */ jsx6(
182
- Comp,
183
- {
184
- "data-reveal": reveal === void 0 ? void 0 : "",
185
- "data-interactive": interactive ? "" : void 0,
186
- style: revealStyle,
187
- className: card({ radius, tone, interactive }).root({ className }),
188
- ...props
189
- }
190
- );
191
- }
192
- var ASPECT = { video: "aspect-video", square: "aspect-square", portrait: "aspect-[3/4]", auto: "" };
193
- function CardMedia({ aspect = "video", className, ...props }) {
194
- return /* @__PURE__ */ jsx6("div", { "data-aspect": aspect, className: slots.media({ className: cn(ASPECT[aspect], className) }), ...props });
195
- }
196
- function CardImage({ src, alt = "", fallback, loading = "lazy", className, ...props }) {
197
- if (!src) {
198
- return /* @__PURE__ */ jsx6("div", { "data-fallback": "", "aria-hidden": true, className: slots.fallback({ className }), children: fallback });
199
- }
200
- return /* @__PURE__ */ jsx6("img", { src, alt, loading, decoding: "async", className: slots.image({ className }), ...props });
201
- }
202
- var CORNER = {
203
- "top-left": "left-2.5 top-2.5",
204
- "top-right": "right-2.5 top-2.5",
205
- "bottom-left": "bottom-2.5 left-2.5",
206
- "bottom-right": "bottom-2.5 right-2.5"
207
- };
208
- function CardOverlay({ corner = "top-left", className, ...props }) {
209
- return /* @__PURE__ */ jsx6("div", { "data-corner": corner, className: slots.overlay({ className: cn(CORNER[corner], className) }), ...props });
210
- }
211
- function CardBody({ padding, className, ...props }) {
212
- return /* @__PURE__ */ jsx6("div", { className: card({ padding }).body({ className }), ...props });
213
- }
214
- function CardTitle({ as: Tag = "h3", className, ...props }) {
215
- return /* @__PURE__ */ jsx6(Tag, { className: slots.title({ className }), ...props });
216
- }
217
- function CardDescription({ className, ...props }) {
218
- return /* @__PURE__ */ jsx6("p", { className: slots.description({ className }), ...props });
219
- }
220
- function CardStat({ label, className, children, ...props }) {
221
- return /* @__PURE__ */ jsxs4("div", { className: slots.stat({ className }), ...props, children: [
222
- /* @__PURE__ */ jsx6("p", { className: slots.statLabel(), children: label }),
223
- /* @__PURE__ */ jsx6("p", { className: slots.statValue(), children })
224
- ] });
225
- }
226
- function CardFooter({ className, ...props }) {
227
- return /* @__PURE__ */ jsx6("div", { className: slots.footer({ className }), ...props });
228
- }
229
- var Card = {
230
- Root: CardRoot,
231
- Media: CardMedia,
232
- Image: CardImage,
233
- Overlay: CardOverlay,
234
- Body: CardBody,
235
- Title: CardTitle,
236
- Description: CardDescription,
237
- Stat: CardStat,
238
- Footer: CardFooter
239
- };
240
-
241
147
  // src/media-grid/preview-focus.ts
242
148
  var MIN_RATIO = 0.6;
243
149
  var ratios = /* @__PURE__ */ new Map();
@@ -279,7 +185,7 @@ var subscribeLeader = (l) => (listeners.add(l), () => void listeners.delete(l));
279
185
  var isLeader = (el) => el !== null && leader === el;
280
186
 
281
187
  // src/media-grid/video-card.tsx
282
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
188
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
283
189
  var FRAME = { landscape: "aspect-video", portrait: "aspect-[9/16]" };
284
190
  function VideoCard({
285
191
  title,
@@ -322,7 +228,7 @@ function VideoCard({
322
228
  const { live, arm, disarm } = usePreviewIntent(node, canPreview, previewDelay);
323
229
  const row = layout === "row";
324
230
  const tall = aspect === "portrait" && !row;
325
- return /* @__PURE__ */ jsx7(
231
+ return /* @__PURE__ */ jsx6(
326
232
  "article",
327
233
  {
328
234
  ref: setRef,
@@ -335,10 +241,10 @@ function VideoCard({
335
241
  onFocus: (e) => (arm("focus"), onFocus?.(e)),
336
242
  onBlur: (e) => (disarm("focus"), onBlur?.(e)),
337
243
  ...props,
338
- children: /* @__PURE__ */ jsxs5(Card.Root, { interactive: true, tone: "glass", className: cn("h-full w-full max-w-full", row ? "flex-row" : "flex-col"), children: [
339
- /* @__PURE__ */ jsxs5(Card.Media, { aspect: "auto", className: cn("shrink-0", FRAME[aspect], row && (aspect === "portrait" ? "w-24 sm:w-28" : "w-40 sm:w-56")), children: [
340
- fit === "contain" && poster && /* @__PURE__ */ jsx7("img", { src: poster, alt: "", "aria-hidden": true, loading: "lazy", className: "absolute inset-0 h-full w-full scale-125 object-cover opacity-70 blur-2xl" }),
341
- /* @__PURE__ */ jsx7(
244
+ children: /* @__PURE__ */ jsxs4(Card.Root, { interactive: true, tone: "glass", className: cn("h-full w-full max-w-full", row ? "flex-row" : "flex-col"), children: [
245
+ /* @__PURE__ */ jsxs4(Card.Media, { aspect: "auto", className: cn("shrink-0", FRAME[aspect], row && (aspect === "portrait" ? "w-24 sm:w-28" : "w-40 sm:w-56")), children: [
246
+ fit === "contain" && poster && /* @__PURE__ */ jsx6("img", { src: poster, alt: "", "aria-hidden": true, loading: "lazy", className: "absolute inset-0 h-full w-full scale-125 object-cover opacity-70 blur-2xl" }),
247
+ /* @__PURE__ */ jsx6(
342
248
  Card.Image,
343
249
  {
344
250
  src: poster,
@@ -348,21 +254,21 @@ function VideoCard({
348
254
  className: cn(fit === "contain" && "relative object-contain", blurred && "scale-110 blur-xl")
349
255
  }
350
256
  ),
351
- live && previewSrc && /* @__PURE__ */ jsx7(PreviewLayer, { src: previewSrc, contain: fit === "contain" }),
352
- overlay && /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 z-20 flex", children: overlay }),
353
- badges && /* @__PURE__ */ jsx7(Card.Overlay, { corner: "top-left", className: "theme-dark pointer-events-none flex-wrap", children: badges }),
354
- duration && /* @__PURE__ */ jsx7(Card.Overlay, { corner: "bottom-right", className: "pointer-events-none", children: /* @__PURE__ */ jsx7("span", { className: "rounded-sm bg-scrim px-1.5 py-0.5 font-mono text-[11px] text-fg-on-media", children: duration }) })
257
+ live && previewSrc && /* @__PURE__ */ jsx6(PreviewLayer, { src: previewSrc, contain: fit === "contain" }),
258
+ overlay && /* @__PURE__ */ jsx6("div", { className: "absolute inset-0 z-20 flex", children: overlay }),
259
+ badges && /* @__PURE__ */ jsx6(Card.Overlay, { corner: "top-left", className: "theme-dark pointer-events-none flex-wrap", children: badges }),
260
+ duration && /* @__PURE__ */ jsx6(Card.Overlay, { corner: "bottom-right", className: "pointer-events-none", children: /* @__PURE__ */ jsx6("span", { className: "rounded-sm bg-scrim px-1.5 py-0.5 font-mono text-[11px] text-fg-on-media", children: duration }) })
355
261
  ] }),
356
- /* @__PURE__ */ jsxs5(Card.Body, { className: "static min-w-0 flex-1 justify-between gap-2 p-3", children: [
357
- /* @__PURE__ */ jsx7("h3", { className: "m-0 min-h-[2.5em] text-sm font-semibold leading-tight text-fg", children: /* @__PURE__ */ jsx7(BlockLink, { href, linkAs, className: "line-clamp-2 outline-none after:absolute after:inset-0 after:z-0 after:content-[''] focus-visible:after:ring-2 focus-visible:after:ring-ring", children: title }) }),
358
- /* @__PURE__ */ jsxs5("div", { className: cn("relative z-10 text-xs text-fg-secondary", tall ? "flex flex-col gap-1" : "flex h-8 items-center gap-2"), children: [
359
- creator && /* @__PURE__ */ jsxs5("div", { className: "flex h-6 min-w-0 items-center gap-2", children: [
360
- /* @__PURE__ */ jsx7(Avatar, { src: creator.avatarSrc, defaultAvatar: creator.defaultAvatar, alt: "", fallback: creator.name.charAt(0), size: "xs", className: "shrink-0" }),
361
- creator.href ? /* @__PURE__ */ jsx7(BlockLink, { href: creator.href, linkAs, className: "min-w-0 truncate hover:text-fg", children: creator.name }) : /* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: creator.name })
262
+ /* @__PURE__ */ jsxs4(Card.Body, { className: "static min-w-0 flex-1 justify-between gap-2 p-3", children: [
263
+ /* @__PURE__ */ jsx6("h3", { className: "m-0 min-h-[2.5em] text-sm font-semibold leading-tight text-fg", children: /* @__PURE__ */ jsx6(BlockLink, { href, linkAs, className: "line-clamp-2 outline-none after:absolute after:inset-0 after:z-0 after:content-[''] focus-visible:after:ring-2 focus-visible:after:ring-ring", children: title }) }),
264
+ /* @__PURE__ */ jsxs4("div", { className: cn("relative z-10 text-xs text-fg-secondary", tall ? "flex flex-col gap-1" : "flex h-8 items-center gap-2"), children: [
265
+ creator && /* @__PURE__ */ jsxs4("div", { className: "flex h-6 min-w-0 items-center gap-2", children: [
266
+ /* @__PURE__ */ jsx6(Avatar, { src: creator.avatarSrc, defaultAvatar: creator.defaultAvatar, alt: "", fallback: creator.name.charAt(0), size: "xs", className: "shrink-0" }),
267
+ creator.href ? /* @__PURE__ */ jsx6(BlockLink, { href: creator.href, linkAs, className: "min-w-0 truncate hover:text-fg", children: creator.name }) : /* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate", children: creator.name })
362
268
  ] }),
363
- (meta || action) && /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-2", tall ? "h-7 justify-between" : "ml-auto shrink-0"), children: [
364
- meta && /* @__PURE__ */ jsx7("span", { className: "shrink-0 font-mono text-[11px] text-fg-muted", children: meta }),
365
- action && /* @__PURE__ */ jsx7("span", { className: "shrink-0", children: action })
269
+ (meta || action) && /* @__PURE__ */ jsxs4("div", { className: cn("flex items-center gap-2", tall ? "h-7 justify-between" : "ml-auto shrink-0"), children: [
270
+ meta && /* @__PURE__ */ jsx6("span", { className: "shrink-0 font-mono text-[11px] text-fg-muted", children: meta }),
271
+ action && /* @__PURE__ */ jsx6("span", { className: "shrink-0", children: action })
366
272
  ] })
367
273
  ] })
368
274
  ] })
@@ -372,7 +278,7 @@ function VideoCard({
372
278
  }
373
279
  function PreviewLayer({ src, contain }) {
374
280
  const [ready, setReady] = React3.useState(false);
375
- return /* @__PURE__ */ jsx7(
281
+ return /* @__PURE__ */ jsx6(
376
282
  "img",
377
283
  {
378
284
  src,
@@ -446,39 +352,25 @@ function usePreviewIntent(node, enabled, delay) {
446
352
  return { live: enabled && (causes.size > 0 || wanted && ready), arm, disarm };
447
353
  }
448
354
 
449
- // src/skeleton/skeleton.tsx
450
- import { tv as tv3 } from "tailwind-variants";
451
- import { jsx as jsx8 } from "react/jsx-runtime";
452
- var skeletonVariants = tv3({
453
- base: "kz-skeleton block bg-surface-3",
454
- variants: {
455
- shape: { text: "h-3 w-full rounded-sm", circle: "aspect-square h-10 rounded-full", rect: "h-24 w-full rounded-lg" }
456
- },
457
- defaultVariants: { shape: "text" }
458
- });
459
- function Skeleton({ shape, className, ...props }) {
460
- return /* @__PURE__ */ jsx8("span", { "aria-hidden": true, "data-shape": shape ?? "text", className: skeletonVariants({ shape, className }), ...props });
461
- }
462
-
463
355
  // src/media-grid/video-card-skeleton.tsx
464
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
356
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
465
357
  var FRAME2 = { landscape: "aspect-video", portrait: "aspect-[9/16]" };
466
358
  function VideoCardSkeleton({ aspect = "landscape", layout = "stack", className, ...props }) {
467
359
  const row = layout === "row";
468
360
  const tall = aspect === "portrait" && !row;
469
- return /* @__PURE__ */ jsx9("div", { "aria-hidden": true, "data-skeleton": "video-card", "data-aspect": aspect, "data-layout": layout, className: cn("h-full min-w-0", className), ...props, children: /* @__PURE__ */ jsxs6(Card.Root, { tone: "glass", className: cn("h-full w-full max-w-full", row ? "flex-row" : "flex-col"), children: [
470
- /* @__PURE__ */ jsx9(Card.Media, { aspect: "auto", className: cn("shrink-0", FRAME2[aspect], row && (aspect === "portrait" ? "w-24 sm:w-28" : "w-40 sm:w-56")), children: /* @__PURE__ */ jsx9(Skeleton, { shape: "rect", className: "h-full w-full rounded-none" }) }),
471
- /* @__PURE__ */ jsxs6(Card.Body, { className: "static min-w-0 flex-1 justify-between gap-2 p-3", children: [
472
- /* @__PURE__ */ jsxs6("div", { className: "flex min-h-[2.5em] flex-col justify-center gap-1.5", children: [
473
- /* @__PURE__ */ jsx9(Skeleton, { className: "h-3" }),
474
- /* @__PURE__ */ jsx9(Skeleton, { className: "h-3 w-3/5" })
361
+ return /* @__PURE__ */ jsx7("div", { "aria-hidden": true, "data-skeleton": "video-card", "data-aspect": aspect, "data-layout": layout, className: cn("h-full min-w-0", className), ...props, children: /* @__PURE__ */ jsxs5(Card.Root, { tone: "glass", className: cn("h-full w-full max-w-full", row ? "flex-row" : "flex-col"), children: [
362
+ /* @__PURE__ */ jsx7(Card.Media, { aspect: "auto", className: cn("shrink-0", FRAME2[aspect], row && (aspect === "portrait" ? "w-24 sm:w-28" : "w-40 sm:w-56")), children: /* @__PURE__ */ jsx7(Skeleton, { shape: "rect", className: "h-full w-full rounded-none" }) }),
363
+ /* @__PURE__ */ jsxs5(Card.Body, { className: "static min-w-0 flex-1 justify-between gap-2 p-3", children: [
364
+ /* @__PURE__ */ jsxs5("div", { className: "flex min-h-[2.5em] flex-col justify-center gap-1.5", children: [
365
+ /* @__PURE__ */ jsx7(Skeleton, { className: "h-3" }),
366
+ /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-3/5" })
475
367
  ] }),
476
- /* @__PURE__ */ jsxs6("div", { className: cn("flex text-xs", tall ? "flex-col gap-1" : "h-8 items-center gap-2"), children: [
477
- /* @__PURE__ */ jsxs6("div", { className: "flex h-6 min-w-0 items-center gap-2", children: [
478
- /* @__PURE__ */ jsx9(Skeleton, { shape: "circle", className: "h-6 w-6 shrink-0" }),
479
- /* @__PURE__ */ jsx9(Skeleton, { className: "h-2.5 w-20" })
368
+ /* @__PURE__ */ jsxs5("div", { className: cn("flex text-xs", tall ? "flex-col gap-1" : "h-8 items-center gap-2"), children: [
369
+ /* @__PURE__ */ jsxs5("div", { className: "flex h-6 min-w-0 items-center gap-2", children: [
370
+ /* @__PURE__ */ jsx7(Skeleton, { shape: "circle", className: "h-6 w-6 shrink-0" }),
371
+ /* @__PURE__ */ jsx7(Skeleton, { className: "h-2.5 w-20" })
480
372
  ] }),
481
- /* @__PURE__ */ jsx9("div", { className: cn("flex items-center", tall ? "h-7" : "ml-auto"), children: /* @__PURE__ */ jsx9(Skeleton, { className: "h-2.5 w-14" }) })
373
+ /* @__PURE__ */ jsx7("div", { className: cn("flex items-center", tall ? "h-7" : "ml-auto"), children: /* @__PURE__ */ jsx7(Skeleton, { className: "h-2.5 w-14" }) })
482
374
  ] })
483
375
  ] })
484
376
  ] }) });
@@ -489,13 +381,13 @@ var GRID2 = {
489
381
  };
490
382
  function MediaGridSkeleton({ label, count = 8, shelfCount = 0, layout = "grid", frame = "landscape", className, ...props }) {
491
383
  const row = layout === "list";
492
- return /* @__PURE__ */ jsxs6("div", { role: "status", "aria-busy": "true", "data-media-grid-skeleton": "", className: cn("flex min-w-0 flex-col gap-8", className), ...props, children: [
493
- /* @__PURE__ */ jsx9("span", { className: "sr-only", children: label }),
494
- shelfCount > 0 && /* @__PURE__ */ jsxs6("div", { "aria-hidden": true, className: "min-w-0", children: [
495
- /* @__PURE__ */ jsx9(Skeleton, { className: "mb-3 h-4 w-24" }),
496
- /* @__PURE__ */ jsx9("ul", { className: "m-0 flex list-none items-stretch gap-3 overflow-hidden p-0", children: Array.from({ length: shelfCount }, (_, i) => /* @__PURE__ */ jsx9("li", { className: "w-[9.5rem] shrink-0 sm:w-44", children: /* @__PURE__ */ jsx9(VideoCardSkeleton, { aspect: "portrait" }) }, i)) })
384
+ return /* @__PURE__ */ jsxs5("div", { role: "status", "aria-busy": "true", "data-media-grid-skeleton": "", className: cn("flex min-w-0 flex-col gap-8", className), ...props, children: [
385
+ /* @__PURE__ */ jsx7("span", { className: "sr-only", children: label }),
386
+ shelfCount > 0 && /* @__PURE__ */ jsxs5("div", { "aria-hidden": true, className: "min-w-0", children: [
387
+ /* @__PURE__ */ jsx7(Skeleton, { className: "mb-3 h-4 w-24" }),
388
+ /* @__PURE__ */ jsx7("ul", { className: "m-0 flex list-none items-stretch gap-3 overflow-hidden p-0", children: Array.from({ length: shelfCount }, (_, i) => /* @__PURE__ */ jsx7("li", { className: "w-[9.5rem] shrink-0 sm:w-44", children: /* @__PURE__ */ jsx7(VideoCardSkeleton, { aspect: "portrait" }) }, i)) })
497
389
  ] }),
498
- /* @__PURE__ */ jsx9("ul", { "aria-hidden": true, className: cn("m-0 grid list-none auto-rows-fr gap-4 p-0", row ? "grid-cols-1" : GRID2[frame]), children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx9("li", { className: "min-w-0", children: /* @__PURE__ */ jsx9(VideoCardSkeleton, { aspect: frame, layout: row ? "row" : "stack" }) }, i)) })
390
+ /* @__PURE__ */ jsx7("ul", { "aria-hidden": true, className: cn("m-0 grid list-none auto-rows-fr gap-4 p-0", row ? "grid-cols-1" : GRID2[frame]), children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx7("li", { className: "min-w-0", children: /* @__PURE__ */ jsx7(VideoCardSkeleton, { aspect: frame, layout: row ? "row" : "stack" }) }, i)) })
499
391
  ] });
500
392
  }
501
393
  export {