@krizaka/ui 3.20.0 → 3.21.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 (197) hide show
  1. package/dist/action-bar.js +4 -4
  2. package/dist/argument-card.js +1 -1
  3. package/dist/blocks.css +1 -1
  4. package/dist/button.js +3 -2
  5. package/dist/card.js +3 -3
  6. package/dist/{chunk-2NB27LM7.js → chunk-3IN6TOPM.js} +4 -4
  7. package/dist/{chunk-VDR2EP6K.js → chunk-4QN5YJ3D.js} +17 -5
  8. package/dist/chunk-4QN5YJ3D.js.map +1 -0
  9. package/dist/chunk-TDG7ED2W.js +1 -0
  10. package/dist/chunk-TDG7ED2W.js.map +1 -0
  11. package/dist/code-block.js +17 -5
  12. package/dist/code-block.js.map +1 -1
  13. package/dist/date-picker.js +2 -2
  14. package/dist/date-picker.js.map +1 -1
  15. package/dist/force-update-screen.d.ts +80 -0
  16. package/dist/force-update-screen.js +38 -0
  17. package/dist/force-update-screen.js.map +1 -0
  18. package/dist/maintenance-screen.d.ts +68 -0
  19. package/dist/maintenance-screen.js +35 -0
  20. package/dist/maintenance-screen.js.map +1 -0
  21. package/dist/media-grid.js +1 -1
  22. package/dist/media-grid.js.map +1 -1
  23. package/dist/native.d.ts +68 -1
  24. package/dist/native.js +767 -681
  25. package/dist/native.js.map +1 -1
  26. package/dist/nav-bar.d.ts +30 -7
  27. package/dist/nav-bar.js +69 -15
  28. package/dist/nav-bar.js.map +1 -1
  29. package/dist/page-hero.js +3 -3
  30. package/dist/radio-group.js +1 -1
  31. package/dist/settings-layout.js +1 -1
  32. package/dist/settings-layout.js.map +1 -1
  33. package/dist/tabs.js +2 -2
  34. package/dist/tabs.js.map +1 -1
  35. package/dist/update-prompt.d.ts +86 -0
  36. package/dist/update-prompt.js +41 -0
  37. package/dist/update-prompt.js.map +1 -0
  38. package/dist/video-player.d.ts +1 -1
  39. package/dist/video-player.js +16 -3
  40. package/dist/video-player.js.map +1 -1
  41. package/package.json +51 -9
  42. package/registry/achievement.json +1 -1
  43. package/registry/action-bar.json +1 -1
  44. package/registry/activity-feed.json +1 -1
  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 +1 -1
  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/chat.json +1 -1
  58. package/registry/checkbox.json +1 -1
  59. package/registry/chip-link.json +1 -1
  60. package/registry/chip.json +1 -1
  61. package/registry/choice-grid.json +1 -1
  62. package/registry/code-block.json +1 -1
  63. package/registry/combobox.json +1 -1
  64. package/registry/command.json +1 -1
  65. package/registry/component-page.json +1 -1
  66. package/registry/confirm-button.json +1 -1
  67. package/registry/contact-page.json +1 -1
  68. package/registry/continue-prompt.json +1 -1
  69. package/registry/countdown.json +1 -1
  70. package/registry/cta-panel.json +1 -1
  71. package/registry/dashboard-layout.json +1 -1
  72. package/registry/data-table.json +1 -1
  73. package/registry/date-picker.json +3 -3
  74. package/registry/decision-list.json +1 -1
  75. package/registry/description-list.json +1 -1
  76. package/registry/detail-layout.json +1 -1
  77. package/registry/dialog.json +1 -1
  78. package/registry/docs-article-page.json +1 -1
  79. package/registry/docs-hub-page.json +1 -1
  80. package/registry/docs-layout.json +1 -1
  81. package/registry/document-viewer.json +1 -1
  82. package/registry/dropdown-menu.json +1 -1
  83. package/registry/empty-state.json +1 -1
  84. package/registry/error-page.json +1 -1
  85. package/registry/examples/force-update-screen/default.d.ts +4 -0
  86. package/registry/examples/force-update-screen/default.js +25 -0
  87. package/registry/examples/force-update-screen/default.tsx +19 -0
  88. package/registry/examples/force-update-screen/native/default.d.ts +4 -0
  89. package/registry/examples/force-update-screen/native/default.dark.png +0 -0
  90. package/registry/examples/force-update-screen/native/default.js +24 -0
  91. package/registry/examples/force-update-screen/native/default.light.png +0 -0
  92. package/registry/examples/force-update-screen/native/default.tsx +18 -0
  93. package/registry/examples/maintenance-screen/default.d.ts +4 -0
  94. package/registry/examples/maintenance-screen/default.js +22 -0
  95. package/registry/examples/maintenance-screen/default.tsx +16 -0
  96. package/registry/examples/maintenance-screen/native/default.d.ts +4 -0
  97. package/registry/examples/maintenance-screen/native/default.dark.png +0 -0
  98. package/registry/examples/maintenance-screen/native/default.js +21 -0
  99. package/registry/examples/maintenance-screen/native/default.light.png +0 -0
  100. package/registry/examples/maintenance-screen/native/default.tsx +15 -0
  101. package/registry/examples/nav-bar/family-product.js +16 -13
  102. package/registry/examples/nav-bar/family-product.tsx +19 -19
  103. package/registry/examples/update-prompt/default.d.ts +4 -0
  104. package/registry/examples/update-prompt/default.js +24 -0
  105. package/registry/examples/update-prompt/default.tsx +18 -0
  106. package/registry/examples/update-prompt/native/default.d.ts +4 -0
  107. package/registry/examples/update-prompt/native/default.dark.png +0 -0
  108. package/registry/examples/update-prompt/native/default.js +23 -0
  109. package/registry/examples/update-prompt/native/default.light.png +0 -0
  110. package/registry/examples/update-prompt/native/default.tsx +17 -0
  111. package/registry/field.json +1 -1
  112. package/registry/file-upload.json +1 -1
  113. package/registry/filter-bar.json +1 -1
  114. package/registry/force-update-screen.json +323 -0
  115. package/registry/form.json +1 -1
  116. package/registry/gallery-page.json +1 -1
  117. package/registry/glow-card.json +1 -1
  118. package/registry/goal-gauge.json +1 -1
  119. package/registry/how-it-works-page.json +1 -1
  120. package/registry/image-cropper.json +1 -1
  121. package/registry/index.json +97 -4
  122. package/registry/iso.json +1 -1
  123. package/registry/kanban.json +1 -1
  124. package/registry/kbd.json +1 -1
  125. package/registry/landing-page.json +1 -1
  126. package/registry/landscape.json +1 -1
  127. package/registry/legal-page.json +1 -1
  128. package/registry/link-card.json +1 -1
  129. package/registry/list.json +1 -1
  130. package/registry/loader.json +1 -1
  131. package/registry/longform-page.json +1 -1
  132. package/registry/maintenance-screen.json +259 -0
  133. package/registry/map.json +2 -2
  134. package/registry/markdown.json +1 -1
  135. package/registry/marketing-layout.json +1 -1
  136. package/registry/marquee.json +1 -1
  137. package/registry/mascot-quote.json +1 -1
  138. package/registry/mascot-state.json +1 -1
  139. package/registry/mascots.json +1 -1
  140. package/registry/match-dialog.json +1 -1
  141. package/registry/media-capture.json +1 -1
  142. package/registry/media-grid.json +2 -2
  143. package/registry/meter.json +1 -1
  144. package/registry/nav-bar.json +47 -14
  145. package/registry/number-ticker.json +1 -1
  146. package/registry/page-header.json +1 -1
  147. package/registry/page-hero.json +1 -1
  148. package/registry/page.json +1 -1
  149. package/registry/pagination.json +1 -1
  150. package/registry/photo-grid.json +1 -1
  151. package/registry/pointer-light.json +1 -1
  152. package/registry/popover.json +1 -1
  153. package/registry/pricing-page.json +1 -1
  154. package/registry/product-page.json +1 -1
  155. package/registry/profile-card.json +1 -1
  156. package/registry/progress.json +1 -1
  157. package/registry/promise-card.json +1 -1
  158. package/registry/radio-group.json +2 -2
  159. package/registry/recipes.json +1 -1
  160. package/registry/scroll-stage.json +1 -1
  161. package/registry/search-field.json +1 -1
  162. package/registry/section-backdrop.json +1 -1
  163. package/registry/separator.json +1 -1
  164. package/registry/settings-layout.json +2 -2
  165. package/registry/showcase.json +1 -1
  166. package/registry/site-footer.json +2 -2
  167. package/registry/sites.json +1 -1
  168. package/registry/skeleton.json +1 -1
  169. package/registry/skip-link.json +1 -1
  170. package/registry/slider.json +1 -1
  171. package/registry/slot.json +1 -1
  172. package/registry/spinner.json +1 -1
  173. package/registry/split-view.json +1 -1
  174. package/registry/stage-banner.json +1 -1
  175. package/registry/stat.json +1 -1
  176. package/registry/status-page.json +1 -1
  177. package/registry/step-progress.json +1 -1
  178. package/registry/stepper.json +1 -1
  179. package/registry/swipe-deck.json +1 -1
  180. package/registry/switch.json +1 -1
  181. package/registry/tabs.json +3 -3
  182. package/registry/tag-input.json +1 -1
  183. package/registry/tag-selector.json +1 -1
  184. package/registry/terminal-replay.json +1 -1
  185. package/registry/theme.json +1 -1
  186. package/registry/toast.json +1 -1
  187. package/registry/toc.json +1 -1
  188. package/registry/tooltip.json +1 -1
  189. package/registry/tree-view.json +1 -1
  190. package/registry/update-prompt.json +316 -0
  191. package/registry/verified-badge.json +1 -1
  192. package/registry/vertical-video.json +1 -1
  193. package/registry/video-player.json +4 -4
  194. package/registry/video-trimmer.json +1 -1
  195. package/registry/virtual.json +1 -1
  196. package/dist/chunk-VDR2EP6K.js.map +0 -1
  197. /package/dist/{chunk-2NB27LM7.js.map → chunk-3IN6TOPM.js.map} +0 -0
@@ -5,14 +5,14 @@ import {
5
5
  import {
6
6
  ExternalGlyph
7
7
  } from "./chunk-XCBVFMNV.js";
8
- import {
9
- buttonVariants
10
- } from "./chunk-2NB27LM7.js";
11
- import "./chunk-2VNYHG4E.js";
12
8
  import {
13
9
  cn
14
10
  } from "./chunk-4LOMIQVX.js";
11
+ import {
12
+ buttonVariants
13
+ } from "./chunk-3IN6TOPM.js";
15
14
  import "./chunk-43PTCDTL.js";
15
+ import "./chunk-2VNYHG4E.js";
16
16
 
17
17
  // src/action-bar/action-bar.tsx
18
18
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -4,11 +4,11 @@ import {
4
4
  import {
5
5
  BlockLink
6
6
  } from "./chunk-2AGSO3WH.js";
7
+ import "./chunk-XVLWVTQA.js";
7
8
  import {
8
9
  ArrowGlyph,
9
10
  ChevronGlyph
10
11
  } from "./chunk-XCBVFMNV.js";
11
- import "./chunk-XVLWVTQA.js";
12
12
  import {
13
13
  cn
14
14
  } from "./chunk-4LOMIQVX.js";
package/dist/blocks.css CHANGED
@@ -584,7 +584,7 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
584
584
  @media (max-width: 1023px) {
585
585
  .kz-toc-layout { grid-template-columns: minmax(0, 1fr); gap: 8px; }
586
586
  .kz-toc-aside { position: static; padding-top: 0; margin-inline: calc(-1 * var(--kz-gutter, 16px)); }
587
- .kz-toc { padding: 0 var(--kz-gutter, 16px) 4px; overflow-x: auto; scrollbar-width: none; }
587
+ .kz-toc { padding: 0 var(--kz-gutter, 16px) 4px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
588
588
  .kz-toc .kz-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
589
589
  .kz-toc ol { margin: 0; display: flex; gap: 8px; width: max-content; border: 0; }
590
590
  .kz-toc a { min-height: 36px; padding: 0 14px; border-radius: 999px; white-space: nowrap; background: var(--kz-surface-1); border: 1px solid var(--kz-border-default); }
package/dist/button.js CHANGED
@@ -1,10 +1,11 @@
1
+ import "./chunk-TDG7ED2W.js";
1
2
  import {
2
3
  Button,
3
4
  IconButton,
4
5
  buttonVariants
5
- } from "./chunk-2NB27LM7.js";
6
- import "./chunk-2VNYHG4E.js";
6
+ } from "./chunk-3IN6TOPM.js";
7
7
  import "./chunk-43PTCDTL.js";
8
+ import "./chunk-2VNYHG4E.js";
8
9
  export {
9
10
  Button,
10
11
  IconButton,
package/dist/card.js CHANGED
@@ -1,9 +1,9 @@
1
- import {
2
- defineRecipe
3
- } from "./chunk-2VNYHG4E.js";
4
1
  import {
5
2
  cn
6
3
  } from "./chunk-4LOMIQVX.js";
4
+ import {
5
+ defineRecipe
6
+ } from "./chunk-2VNYHG4E.js";
7
7
 
8
8
  // src/card/card.tsx
9
9
  import { Slot } from "radix-ui";
@@ -1,9 +1,9 @@
1
- import {
2
- defineRecipe
3
- } from "./chunk-2VNYHG4E.js";
4
1
  import {
5
2
  LoaderGlyph
6
3
  } from "./chunk-43PTCDTL.js";
4
+ import {
5
+ defineRecipe
6
+ } from "./chunk-2VNYHG4E.js";
7
7
 
8
8
  // src/button/button.tsx
9
9
  import { Slot } from "radix-ui";
@@ -107,4 +107,4 @@ export {
107
107
  Button,
108
108
  IconButton
109
109
  };
110
- //# sourceMappingURL=chunk-2NB27LM7.js.map
110
+ //# sourceMappingURL=chunk-3IN6TOPM.js.map
@@ -3,7 +3,7 @@
3
3
  // src/sliding-indicator.ts
4
4
  import * as React from "react";
5
5
  var useIsoLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;
6
- function useSlidingIndicator({ item, active, follow = false }) {
6
+ function useSlidingIndicator({ item, active, prefer, follow = false }) {
7
7
  const ref = React.useRef(null);
8
8
  const place = React.useCallback((target) => {
9
9
  const list = ref.current;
@@ -20,7 +20,19 @@ function useSlidingIndicator({ item, active, follow = false }) {
20
20
  list.style.setProperty("--kz-ind-h", `${a.height}px`);
21
21
  list.setAttribute("data-indicator", "on");
22
22
  }, []);
23
- const rest = React.useCallback(() => place(ref.current?.querySelector(active) ?? null), [place, active]);
23
+ const rest = React.useCallback(
24
+ () => {
25
+ const list = ref.current;
26
+ const hovered = follow ? list?.querySelector(`${item}:hover`) : null;
27
+ place((prefer ? list?.querySelector(prefer) : null) ?? hovered ?? list?.querySelector(active) ?? null);
28
+ },
29
+ [place, active, prefer, item, follow]
30
+ );
31
+ const follow_ = React.useCallback((target) => {
32
+ const hit = target instanceof Element ? target.closest(item) : null;
33
+ if (hit && ref.current?.contains(hit)) place(hit);
34
+ else rest();
35
+ }, [item, place, rest]);
24
36
  useIsoLayoutEffect(() => {
25
37
  const list = ref.current;
26
38
  if (!list) return;
@@ -35,9 +47,9 @@ function useSlidingIndicator({ item, active, follow = false }) {
35
47
  };
36
48
  }, [rest]);
37
49
  const handlers = follow ? {
38
- onPointerOver: (e) => place(e.target.closest(item)),
50
+ onPointerOver: (e) => follow_(e.target),
39
51
  onPointerLeave: rest,
40
- onFocus: (e) => place(e.target.closest(item)),
52
+ onFocus: (e) => follow_(e.target),
41
53
  onBlur: rest
42
54
  } : {};
43
55
  return { ref, handlers };
@@ -46,4 +58,4 @@ function useSlidingIndicator({ item, active, follow = false }) {
46
58
  export {
47
59
  useSlidingIndicator
48
60
  };
49
- //# sourceMappingURL=chunk-VDR2EP6K.js.map
61
+ //# sourceMappingURL=chunk-4QN5YJ3D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sliding-indicator.ts"],"sourcesContent":["// The shared sliding indicator (NavBar, Tabs): one element that glides from item to item instead of each item lighting\n// up on its own. It writes the target's box as CSS variables on the list (`--kz-ind-x/y/w/h`) and `data-indicator=\"on\"`\n// — no re-render, no animation frame: the glide is a CSS transition (none under reduced motion). Before hydration the\n// items keep their own active style, so nothing flashes.\nimport * as React from \"react\";\n\nconst useIsoLayoutEffect = typeof window === \"undefined\" ? React.useEffect : React.useLayoutEffect;\n\n/**\n * `item`: the selector of an item; `active`: of the current one, where the light rests; `prefer`: an item that, when\n * present, holds the light before the current one (the NavBar's open menu); `follow`: the light follows the pointer\n * and the focus — over anything that is not an item (an open menu's panel) it goes back to rest.\n */\nexport function useSlidingIndicator<T extends HTMLElement>({ item, active, prefer, follow = false }: { item: string; active: string; prefer?: string; follow?: boolean }) {\n const ref = React.useRef<T>(null);\n const place = React.useCallback((target: Element | null) => {\n const list = ref.current;\n if (!list) return;\n if (!(target instanceof HTMLElement) || !list.contains(target)) {\n list.removeAttribute(\"data-indicator\");\n return;\n }\n const a = target.getBoundingClientRect();\n const b = list.getBoundingClientRect();\n list.style.setProperty(\"--kz-ind-x\", `${a.left - b.left + list.scrollLeft}px`);\n list.style.setProperty(\"--kz-ind-y\", `${a.top - b.top + list.scrollTop}px`);\n list.style.setProperty(\"--kz-ind-w\", `${a.width}px`);\n list.style.setProperty(\"--kz-ind-h\", `${a.height}px`);\n list.setAttribute(\"data-indicator\", \"on\");\n }, []);\n const rest = React.useCallback(\n () => {\n const list = ref.current;\n // An item re-rendered under a resting pointer (a menu closing) keeps the light the pointer gave it.\n const hovered = follow ? list?.querySelector(`${item}:hover`) : null;\n place((prefer ? list?.querySelector(prefer) : null) ?? hovered ?? list?.querySelector(active) ?? null);\n },\n [place, active, prefer, item, follow],\n );\n const follow_ = React.useCallback((target: EventTarget) => {\n const hit = target instanceof Element ? target.closest(item) : null;\n if (hit && ref.current?.contains(hit)) place(hit);\n else rest();\n }, [item, place, rest]);\n\n useIsoLayoutEffect(() => {\n const list = ref.current;\n if (!list) return;\n rest();\n const resize = new ResizeObserver(rest);\n resize.observe(list);\n const changes = new MutationObserver(rest);\n changes.observe(list, { subtree: true, attributes: true, attributeFilter: [\"data-state\", \"aria-current\", \"data-active\"] });\n return () => {\n resize.disconnect();\n changes.disconnect();\n };\n }, [rest]);\n\n const handlers = follow\n ? {\n onPointerOver: (e: React.PointerEvent) => follow_(e.target),\n onPointerLeave: rest,\n onFocus: (e: React.FocusEvent) => follow_(e.target),\n onBlur: rest,\n }\n : {};\n return { ref, handlers };\n}\n"],"mappings":";;;AAIA,YAAY,WAAW;AAEvB,IAAM,qBAAqB,OAAO,WAAW,cAAoB,kBAAkB;AAO5E,SAAS,oBAA2C,EAAE,MAAM,QAAQ,QAAQ,SAAS,MAAM,GAAwE;AACxK,QAAM,MAAY,aAAU,IAAI;AAChC,QAAM,QAAc,kBAAY,CAAC,WAA2B;AAC1D,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAM;AACX,QAAI,EAAE,kBAAkB,gBAAgB,CAAC,KAAK,SAAS,MAAM,GAAG;AAC9D,WAAK,gBAAgB,gBAAgB;AACrC;AAAA,IACF;AACA,UAAM,IAAI,OAAO,sBAAsB;AACvC,UAAM,IAAI,KAAK,sBAAsB;AACrC,SAAK,MAAM,YAAY,cAAc,GAAG,EAAE,OAAO,EAAE,OAAO,KAAK,UAAU,IAAI;AAC7E,SAAK,MAAM,YAAY,cAAc,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,IAAI;AAC1E,SAAK,MAAM,YAAY,cAAc,GAAG,EAAE,KAAK,IAAI;AACnD,SAAK,MAAM,YAAY,cAAc,GAAG,EAAE,MAAM,IAAI;AACpD,SAAK,aAAa,kBAAkB,IAAI;AAAA,EAC1C,GAAG,CAAC,CAAC;AACL,QAAM,OAAa;AAAA,IACjB,MAAM;AACJ,YAAM,OAAO,IAAI;AAEjB,YAAM,UAAU,SAAS,MAAM,cAAc,GAAG,IAAI,QAAQ,IAAI;AAChE,aAAO,SAAS,MAAM,cAAc,MAAM,IAAI,SAAS,WAAW,MAAM,cAAc,MAAM,KAAK,IAAI;AAAA,IACvG;AAAA,IACA,CAAC,OAAO,QAAQ,QAAQ,MAAM,MAAM;AAAA,EACtC;AACA,QAAM,UAAgB,kBAAY,CAAC,WAAwB;AACzD,UAAM,MAAM,kBAAkB,UAAU,OAAO,QAAQ,IAAI,IAAI;AAC/D,QAAI,OAAO,IAAI,SAAS,SAAS,GAAG,EAAG,OAAM,GAAG;AAAA,QAC3C,MAAK;AAAA,EACZ,GAAG,CAAC,MAAM,OAAO,IAAI,CAAC;AAEtB,qBAAmB,MAAM;AACvB,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAM;AACX,SAAK;AACL,UAAM,SAAS,IAAI,eAAe,IAAI;AACtC,WAAO,QAAQ,IAAI;AACnB,UAAM,UAAU,IAAI,iBAAiB,IAAI;AACzC,YAAQ,QAAQ,MAAM,EAAE,SAAS,MAAM,YAAY,MAAM,iBAAiB,CAAC,cAAc,gBAAgB,aAAa,EAAE,CAAC;AACzH,WAAO,MAAM;AACX,aAAO,WAAW;AAClB,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,WAAW,SACb;AAAA,IACE,eAAe,CAAC,MAA0B,QAAQ,EAAE,MAAM;AAAA,IAC1D,gBAAgB;AAAA,IAChB,SAAS,CAAC,MAAwB,QAAQ,EAAE,MAAM;AAAA,IAClD,QAAQ;AAAA,EACV,IACA,CAAC;AACL,SAAO,EAAE,KAAK,SAAS;AACzB;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-TDG7ED2W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -18,7 +18,7 @@ import { tv } from "tailwind-variants";
18
18
  // src/sliding-indicator.ts
19
19
  import * as React from "react";
20
20
  var useIsoLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;
21
- function useSlidingIndicator({ item, active, follow = false }) {
21
+ function useSlidingIndicator({ item, active, prefer, follow = false }) {
22
22
  const ref = React.useRef(null);
23
23
  const place = React.useCallback((target) => {
24
24
  const list = ref.current;
@@ -35,7 +35,19 @@ function useSlidingIndicator({ item, active, follow = false }) {
35
35
  list.style.setProperty("--kz-ind-h", `${a.height}px`);
36
36
  list.setAttribute("data-indicator", "on");
37
37
  }, []);
38
- const rest = React.useCallback(() => place(ref.current?.querySelector(active) ?? null), [place, active]);
38
+ const rest = React.useCallback(
39
+ () => {
40
+ const list = ref.current;
41
+ const hovered = follow ? list?.querySelector(`${item}:hover`) : null;
42
+ place((prefer ? list?.querySelector(prefer) : null) ?? hovered ?? list?.querySelector(active) ?? null);
43
+ },
44
+ [place, active, prefer, item, follow]
45
+ );
46
+ const follow_ = React.useCallback((target) => {
47
+ const hit = target instanceof Element ? target.closest(item) : null;
48
+ if (hit && ref.current?.contains(hit)) place(hit);
49
+ else rest();
50
+ }, [item, place, rest]);
39
51
  useIsoLayoutEffect(() => {
40
52
  const list = ref.current;
41
53
  if (!list) return;
@@ -50,9 +62,9 @@ function useSlidingIndicator({ item, active, follow = false }) {
50
62
  };
51
63
  }, [rest]);
52
64
  const handlers = follow ? {
53
- onPointerOver: (e) => place(e.target.closest(item)),
65
+ onPointerOver: (e) => follow_(e.target),
54
66
  onPointerLeave: rest,
55
- onFocus: (e) => place(e.target.closest(item)),
67
+ onFocus: (e) => follow_(e.target),
56
68
  onBlur: rest
57
69
  } : {};
58
70
  return { ref, handlers };
@@ -83,7 +95,7 @@ var tabs = tv({
83
95
  },
84
96
  /* Pills that scroll sideways on a phone: a feed's sections. */
85
97
  pills: {
86
- list: "gap-1.5 overflow-x-auto overscroll-x-contain [scrollbar-width:none] data-[orientation=horizontal]:pb-1 before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-full before:border before:border-accent before:bg-accent-soft",
98
+ list: "gap-1.5 overflow-x-auto overflow-y-hidden overscroll-x-contain pt-1 -mt-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-full before:border before:border-accent before:bg-accent-soft",
87
99
  trigger: "h-9 rounded-full border border-border-default bg-surface-1 px-4 text-xs text-fg-secondary hover:border-border-strong hover:text-fg data-[state=active]:border-accent data-[state=active]:bg-accent-soft data-[state=active]:text-fg group-data-[indicator=on]/tabs:data-[state=active]:border-transparent group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent"
88
100
  }
89
101
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/code-block/code-block.tsx","../src/tabs/tabs.tsx","../src/sliding-indicator.ts","../src/code-block/tokens.tsx","../src/code-block/highlighter.ts"],"sourcesContent":["// Client (the copy button, the tabs). A sample of code (blocks.css): its language and its file name, the code\n// highlighted by TanStack Highlight (it scrolls sideways, never shrinks, and takes the keyboard's focus to scroll),\n// lines numbered or set apart (highlighted, added, removed, in focus), a copy button that says it copied in a polite\n// live region. CodeTabs puts several ways to write the same thing (Maven · Gradle · npm) under\n// the tabs of @krizaka/ui.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { CheckGlyph, CopyGlyph } from \"../glyphs\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"../tabs/tabs\";\nimport { type CodeAnnotation, highlight } from \"./tokens\";\n\nexport type CodeBlockProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The code, as it is copied. */\n code: string;\n /**\n * Its language, shown as a tag and used by the highlighter: `ts`, `tsx`, `js`, `jsx`, `json`, `yaml`, `bash`, `html`\n * (`xml`), `css`, `java`, `kotlin`, `diff`, `properties`. Another one is shown as plain text.\n */\n language?: string;\n /** The file it belongs in (`pom.xml`, `application.yml`), or what it is (`Terminal`). */\n file?: React.ReactNode;\n /** The copy button's words, passed translated. Without them there is no copy button (a sample inside a text, say). */\n copyLabel?: string;\n /** What the button says once the code is copied (announced politely). */\n copiedLabel?: string;\n /**\n * Colours comments, strings, keywords, types, tags and numbers (the tokens' roles).\n * @default true\n */\n highlight?: boolean;\n /** A number before every line. */\n lineNumbers?: boolean;\n /** Lines set apart: `highlight`, `added`, `removed`, `error`, `warning`, `dim`, or `focus` (all the others are dimmed). */\n annotations?: readonly CodeAnnotation[];\n /** Called after the code is copied. */\n onCopy?: () => void;\n};\n\n/** A code sample: language and file name, highlighted code that scrolls sideways, a copy button. */\nexport function CodeBlock({ code, language = \"text\", file, copyLabel, copiedLabel, highlight: colour = true, lineNumbers, annotations, onCopy, className, ...props }: CodeBlockProps) {\n const [copied, setCopied] = React.useState(false);\n React.useEffect(() => {\n if (!copied) return;\n const t = setTimeout(() => setCopied(false), 1800);\n return () => clearTimeout(t);\n }, [copied]);\n const copy = () =>\n navigator.clipboard?.writeText(code).then(() => {\n setCopied(true);\n onCopy?.();\n });\n return (\n <figure className={cn(\"kz-code\", className)} {...props}>\n {file || language !== \"text\" || copyLabel ? (\n <figcaption className=\"kz-code-bar\">\n <span className=\"kz-code-file\">\n {language !== \"text\" && <span className=\"kz-code-lang\">{language}</span>}\n {file}\n </span>\n {copyLabel ? (\n <button type=\"button\" className=\"kz-code-copy\" onClick={copy} data-copied={copied ? \"\" : undefined}>\n {copied ? <CheckGlyph className=\"h-3.5 w-3.5\" /> : <CopyGlyph className=\"h-3.5 w-3.5\" />}\n <span aria-live=\"polite\">{copied ? (copiedLabel ?? copyLabel) : copyLabel}</span>\n </button>\n ) : null}\n </figcaption>\n ) : null}\n <pre tabIndex={0} className={lineNumbers ? \"th-code--line-numbers\" : undefined} data-focus={annotations?.some((a) => a.kind === \"focus\") ? \"\" : undefined}>\n <code data-language={language}>{colour ? highlight(code, language, { lineNumbers, annotations }) : code}</code>\n </pre>\n </figure>\n );\n}\n\nexport type CodeTabsProps = Omit<React.HTMLAttributes<HTMLDivElement>, \"dir\" | \"defaultValue\"> & {\n /** What the tabs choose between (`Build tool`): the tab list's accessible name. */\n label: string;\n /** The ways to write it: an id, the tab's words, its sample (a `CodeBlock`). */\n tabs: readonly { id: string; label: React.ReactNode; content: React.ReactNode }[];\n /** The tab open at first. Defaults to the first one. */\n defaultValue?: string;\n};\n\n/** Several ways to write the same thing (Maven · Gradle · npm): segmented tabs above code samples. */\nexport function CodeTabs({ label, tabs, defaultValue, className, ...props }: CodeTabsProps) {\n return (\n <TabsRoot defaultValue={defaultValue ?? tabs[0]?.id} variant=\"segmented\" className={cn(\"kz-code-tabs\", className)} {...props}>\n <TabsList aria-label={label}>\n {tabs.map((t) => (\n <TabsTrigger key={t.id} value={t.id}>\n {t.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {tabs.map((t) => (\n <TabsContent key={t.id} value={t.id}>\n {t.content}\n </TabsContent>\n ))}\n </TabsRoot>\n );\n}\n","// Client (a context). Radix Tabs does the roles (tablist, tab, tabpanel), the aria-selected / aria-controls wiring,\n// the roving focus (arrows, Home, End) and automatic activation: this file only holds the three looks.\nimport { Tabs as TabsPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const tabs = tv({\n slots: {\n root: \"flex gap-4 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row\",\n // One light glides from the active tab to the next (`before:`, placed by useSlidingIndicator); until it is placed\n // (server render), each trigger carries its own active style.\n list:\n \"group/tabs relative isolate flex shrink-0 data-[orientation=vertical]:flex-col \" +\n \"before:pointer-events-none before:absolute before:-z-10 before:opacity-0 before:transition-[translate,width,height,opacity] before:duration-300 \" +\n \"motion-reduce:before:transition-none data-[indicator=on]:before:opacity-100\",\n trigger:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40\",\n content: \"kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n variants: {\n variant: {\n /* The section of a page: a line under the list, the active tab underlined in the accent. */\n underline: {\n list:\n \"gap-1 border-border-default data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-r before:rounded-full before:bg-accent \" +\n \"data-[orientation=horizontal]:before:-bottom-px data-[orientation=horizontal]:before:left-0 data-[orientation=horizontal]:before:h-0.5 \" +\n \"data-[orientation=horizontal]:before:w-(--kz-ind-w) data-[orientation=horizontal]:before:translate-x-(--kz-ind-x) \" +\n \"data-[orientation=vertical]:before:-right-px data-[orientation=vertical]:before:top-0 data-[orientation=vertical]:before:w-0.5 \" +\n \"data-[orientation=vertical]:before:h-(--kz-ind-h) data-[orientation=vertical]:before:translate-y-(--kz-ind-y)\",\n trigger:\n \"relative rounded-md px-3 py-2.5 text-sm text-fg-secondary hover:text-fg data-[state=active]:text-fg \" +\n \"after:absolute after:rounded-full after:bg-transparent data-[state=active]:after:bg-accent \" +\n \"data-[orientation=horizontal]:after:inset-x-2 data-[orientation=horizontal]:after:-bottom-px data-[orientation=horizontal]:after:h-0.5 \" +\n \"data-[orientation=vertical]:justify-start data-[orientation=vertical]:after:inset-y-1.5 data-[orientation=vertical]:after:-right-px data-[orientation=vertical]:after:w-0.5 \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:after:bg-transparent\",\n },\n /* A view switch: equal segments in a track, the active one filled. */\n segmented: {\n list:\n \"inline-grid auto-cols-fr grid-flow-col gap-1 self-start rounded-xl border border-border-default bg-surface-1 p-1 data-[orientation=vertical]:grid-flow-row \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-lg before:bg-accent before:shadow-sm\",\n trigger:\n \"min-h-8 rounded-lg px-3 py-1.5 text-xs text-fg-secondary hover:bg-surface-2 hover:text-fg \" +\n \"data-[state=active]:bg-accent data-[state=active]:text-on-accent data-[state=active]:shadow-sm data-[state=active]:hover:bg-accent \" +\n \"transition-colors group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent group-data-[indicator=on]/tabs:data-[state=active]:shadow-none\",\n },\n /* Pills that scroll sideways on a phone: a feed's sections. */\n pills: {\n list:\n \"gap-1.5 overflow-x-auto overscroll-x-contain [scrollbar-width:none] data-[orientation=horizontal]:pb-1 \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:border before:border-accent before:bg-accent-soft\",\n trigger:\n \"h-9 rounded-full border border-border-default bg-surface-1 px-4 text-xs text-fg-secondary hover:border-border-strong hover:text-fg \" +\n \"data-[state=active]:border-accent data-[state=active]:bg-accent-soft data-[state=active]:text-fg \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:border-transparent group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent\",\n },\n },\n },\n defaultVariants: { variant: \"underline\" },\n});\n\nexport type TabsVariants = VariantProps<typeof tabs>;\ntype Variant = NonNullable<TabsVariants[\"variant\"]>;\n\nconst VariantContext = React.createContext<Variant>(\"underline\");\n\nexport type TabsRootProps = React.ComponentProps<typeof TabsPrimitive.Root> & {\n /** underline (the sections of a page) · segmented (a view switch) · pills (a feed's sections). */\n variant?: TabsVariants[\"variant\"];\n};\n\n/** `value`/`defaultValue` + `onValueChange`, `orientation` (horizontal by default), `variant` for the list. */\nexport function TabsRoot({ variant = \"underline\", className, ...props }: TabsRootProps) {\n return (\n <VariantContext.Provider value={variant}>\n <TabsPrimitive.Root data-variant={variant} className={tabs({ variant }).root({ className })} {...props} />\n </VariantContext.Provider>\n );\n}\n\n/** The tabs. Name it (`aria-label`) when no heading says what it switches. One light glides to the active tab. */\nexport function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n const variant = React.useContext(VariantContext);\n const { ref } = useSlidingIndicator<HTMLDivElement>({ item: \"[role=tab]\", active: \"[role=tab][data-state=active]\" });\n return <TabsPrimitive.List ref={ref} data-variant={variant} className={tabs({ variant }).list({ className })} {...props} />;\n}\n\nexport function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n const variant = React.useContext(VariantContext);\n return <TabsPrimitive.Trigger className={tabs({ variant }).trigger({ className })} {...props} />;\n}\n\nexport function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content className={tabs().content({ className })} {...props} />;\n}\n\n/** `Tabs.Root/List/Trigger/Content` — `variant` underline · segmented · pills on the root. */\nexport const Tabs = { Root: TabsRoot, List: TabsList, Trigger: TabsTrigger, Content: TabsContent };\n","// The shared sliding indicator (NavBar, Tabs): one element that glides from item to item instead of each item lighting\n// up on its own. It writes the target's box as CSS variables on the list (`--kz-ind-x/y/w/h`) and `data-indicator=\"on\"`\n// — no re-render, no animation frame: the glide is a CSS transition (none under reduced motion). Before hydration the\n// items keep their own active style, so nothing flashes.\nimport * as React from \"react\";\n\nconst useIsoLayoutEffect = typeof window === \"undefined\" ? React.useEffect : React.useLayoutEffect;\n\nexport function useSlidingIndicator<T extends HTMLElement>({ item, active, follow = false }: { item: string; active: string; follow?: boolean }) {\n const ref = React.useRef<T>(null);\n const place = React.useCallback((target: Element | null) => {\n const list = ref.current;\n if (!list) return;\n if (!(target instanceof HTMLElement) || !list.contains(target)) {\n list.removeAttribute(\"data-indicator\");\n return;\n }\n const a = target.getBoundingClientRect();\n const b = list.getBoundingClientRect();\n list.style.setProperty(\"--kz-ind-x\", `${a.left - b.left + list.scrollLeft}px`);\n list.style.setProperty(\"--kz-ind-y\", `${a.top - b.top + list.scrollTop}px`);\n list.style.setProperty(\"--kz-ind-w\", `${a.width}px`);\n list.style.setProperty(\"--kz-ind-h\", `${a.height}px`);\n list.setAttribute(\"data-indicator\", \"on\");\n }, []);\n const rest = React.useCallback(() => place(ref.current?.querySelector(active) ?? null), [place, active]);\n\n useIsoLayoutEffect(() => {\n const list = ref.current;\n if (!list) return;\n rest();\n const resize = new ResizeObserver(rest);\n resize.observe(list);\n const changes = new MutationObserver(rest);\n changes.observe(list, { subtree: true, attributes: true, attributeFilter: [\"data-state\", \"aria-current\", \"data-active\"] });\n return () => {\n resize.disconnect();\n changes.disconnect();\n };\n }, [rest]);\n\n const handlers = follow\n ? {\n onPointerOver: (e: React.PointerEvent) => place((e.target as Element).closest(item)),\n onPointerLeave: rest,\n onFocus: (e: React.FocusEvent) => place((e.target as Element).closest(item)),\n onBlur: rest,\n }\n : {};\n return { ref, handlers };\n}\n","// Code → React nodes, from TanStack Highlight's tokens: spans with the `th-*` classes that blocks.css paints with the\n// tokens' text roles (≥ 4.5:1 on the code surface, both themes). No raw HTML: the nodes are elements and text.\nimport { type HighlightDecoration, type HighlightRenderNode, renderTokens } from \"@tanstack/highlight/core\";\nimport * as React from \"react\";\n\nimport { codeHighlighter } from \"./highlighter\";\n\n/** What an annotation says about its lines. */\nexport type AnnotationKind = \"highlight\" | \"added\" | \"removed\" | \"focus\" | \"dim\" | \"error\" | \"warning\";\n\n/** Lines of a sample set apart: one line (`3`) or a range (`[3, 5]`), counted from 1. */\nexport type CodeAnnotation = {\n lines: number | readonly [number, number];\n kind: AnnotationKind;\n};\n\nexport type HighlightOptions = {\n /** A number before every line. */\n lineNumbers?: boolean;\n /** Lines set apart: highlighted, added, removed, in focus (the others are dimmed), dimmed, error, warning. */\n annotations?: readonly CodeAnnotation[];\n};\n\nconst toReact = (node: HighlightRenderNode, key: number): React.ReactNode => {\n if (node.type === \"text\") return node.value;\n const data = Object.fromEntries(Object.entries(node.data ?? {}).map(([name, value]) => [`data-${name}`, value]));\n return React.createElement(\"span\", { key, className: node.classNames.join(\" \"), ...data }, node.children.map(toReact));\n};\n\n/** Splits `code` into text and coloured spans (`th-keyword`, `th-string`…), and into lines when numbered or annotated. */\nexport function highlight(code: string, language = \"text\", { lineNumbers, annotations }: HighlightOptions = {}): React.ReactNode[] {\n const { tokens } = codeHighlighter.tokenize(code, { lang: language });\n const decorations: HighlightDecoration[] = (annotations ?? []).map(({ lines, kind }) => ({ lines, className: `kz-line kz-line-${kind}`, data: { kind } }));\n return renderTokens(tokens, { lineNumbers, decorations }).map(toReact);\n}\n\n/** The language a sample is tokenized in (`bash` → `shell`, `xml` → `html`, unknown → `plaintext`). */\nexport function normalizeCodeLanguage(language?: string): string {\n return codeHighlighter.normalizeLanguage(language);\n}\n","// The highlighter of every code sample: TanStack Highlight (a deterministic, synchronous tokenizer — the same markup on\n// the server and on the client) with the grammars a Krizaka page shows. Each grammar is registered by hand: nothing\n// else is bundled. An unknown language is plain text, never an error.\nimport { createHighlighter } from \"@tanstack/highlight/core\";\nimport { css } from \"@tanstack/highlight/languages/css\";\nimport { diff } from \"@tanstack/highlight/languages/diff\";\nimport { env } from \"@tanstack/highlight/languages/env\";\nimport { html } from \"@tanstack/highlight/languages/html\";\nimport { java } from \"@tanstack/highlight/languages/java\";\nimport { js } from \"@tanstack/highlight/languages/js\";\nimport { json } from \"@tanstack/highlight/languages/json\";\nimport { jsx } from \"@tanstack/highlight/languages/jsx\";\nimport { kotlin } from \"@tanstack/highlight/languages/kotlin\";\nimport { plaintext } from \"@tanstack/highlight/languages/plaintext\";\nimport { shell } from \"@tanstack/highlight/languages/shell\";\nimport { ts } from \"@tanstack/highlight/languages/ts\";\nimport { tsx } from \"@tanstack/highlight/languages/tsx\";\nimport { yaml } from \"@tanstack/highlight/languages/yaml\";\n\n/** The languages a sample can be written in, with the names they answer to (`bash`, `xml`, `yml`, `kt`, `properties`…). */\nexport const codeHighlighter = createHighlighter({\n languages: [css, diff, { ...env, aliases: [...(env.aliases ?? []), \"properties\"] }, html, java, js, json, jsx, kotlin, plaintext, shell, ts, tsx, yaml],\n fallbackLanguage: \"plaintext\",\n});\n"],"mappings":"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","names":["React","React","React","jsx","jsx","tabs"]}
1
+ {"version":3,"sources":["../src/code-block/code-block.tsx","../src/tabs/tabs.tsx","../src/sliding-indicator.ts","../src/code-block/tokens.tsx","../src/code-block/highlighter.ts"],"sourcesContent":["// Client (the copy button, the tabs). A sample of code (blocks.css): its language and its file name, the code\n// highlighted by TanStack Highlight (it scrolls sideways, never shrinks, and takes the keyboard's focus to scroll),\n// lines numbered or set apart (highlighted, added, removed, in focus), a copy button that says it copied in a polite\n// live region. CodeTabs puts several ways to write the same thing (Maven · Gradle · npm) under\n// the tabs of @krizaka/ui.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { CheckGlyph, CopyGlyph } from \"../glyphs\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"../tabs/tabs\";\nimport { type CodeAnnotation, highlight } from \"./tokens\";\n\nexport type CodeBlockProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The code, as it is copied. */\n code: string;\n /**\n * Its language, shown as a tag and used by the highlighter: `ts`, `tsx`, `js`, `jsx`, `json`, `yaml`, `bash`, `html`\n * (`xml`), `css`, `java`, `kotlin`, `diff`, `properties`. Another one is shown as plain text.\n */\n language?: string;\n /** The file it belongs in (`pom.xml`, `application.yml`), or what it is (`Terminal`). */\n file?: React.ReactNode;\n /** The copy button's words, passed translated. Without them there is no copy button (a sample inside a text, say). */\n copyLabel?: string;\n /** What the button says once the code is copied (announced politely). */\n copiedLabel?: string;\n /**\n * Colours comments, strings, keywords, types, tags and numbers (the tokens' roles).\n * @default true\n */\n highlight?: boolean;\n /** A number before every line. */\n lineNumbers?: boolean;\n /** Lines set apart: `highlight`, `added`, `removed`, `error`, `warning`, `dim`, or `focus` (all the others are dimmed). */\n annotations?: readonly CodeAnnotation[];\n /** Called after the code is copied. */\n onCopy?: () => void;\n};\n\n/** A code sample: language and file name, highlighted code that scrolls sideways, a copy button. */\nexport function CodeBlock({ code, language = \"text\", file, copyLabel, copiedLabel, highlight: colour = true, lineNumbers, annotations, onCopy, className, ...props }: CodeBlockProps) {\n const [copied, setCopied] = React.useState(false);\n React.useEffect(() => {\n if (!copied) return;\n const t = setTimeout(() => setCopied(false), 1800);\n return () => clearTimeout(t);\n }, [copied]);\n const copy = () =>\n navigator.clipboard?.writeText(code).then(() => {\n setCopied(true);\n onCopy?.();\n });\n return (\n <figure className={cn(\"kz-code\", className)} {...props}>\n {file || language !== \"text\" || copyLabel ? (\n <figcaption className=\"kz-code-bar\">\n <span className=\"kz-code-file\">\n {language !== \"text\" && <span className=\"kz-code-lang\">{language}</span>}\n {file}\n </span>\n {copyLabel ? (\n <button type=\"button\" className=\"kz-code-copy\" onClick={copy} data-copied={copied ? \"\" : undefined}>\n {copied ? <CheckGlyph className=\"h-3.5 w-3.5\" /> : <CopyGlyph className=\"h-3.5 w-3.5\" />}\n <span aria-live=\"polite\">{copied ? (copiedLabel ?? copyLabel) : copyLabel}</span>\n </button>\n ) : null}\n </figcaption>\n ) : null}\n <pre tabIndex={0} className={lineNumbers ? \"th-code--line-numbers\" : undefined} data-focus={annotations?.some((a) => a.kind === \"focus\") ? \"\" : undefined}>\n <code data-language={language}>{colour ? highlight(code, language, { lineNumbers, annotations }) : code}</code>\n </pre>\n </figure>\n );\n}\n\nexport type CodeTabsProps = Omit<React.HTMLAttributes<HTMLDivElement>, \"dir\" | \"defaultValue\"> & {\n /** What the tabs choose between (`Build tool`): the tab list's accessible name. */\n label: string;\n /** The ways to write it: an id, the tab's words, its sample (a `CodeBlock`). */\n tabs: readonly { id: string; label: React.ReactNode; content: React.ReactNode }[];\n /** The tab open at first. Defaults to the first one. */\n defaultValue?: string;\n};\n\n/** Several ways to write the same thing (Maven · Gradle · npm): segmented tabs above code samples. */\nexport function CodeTabs({ label, tabs, defaultValue, className, ...props }: CodeTabsProps) {\n return (\n <TabsRoot defaultValue={defaultValue ?? tabs[0]?.id} variant=\"segmented\" className={cn(\"kz-code-tabs\", className)} {...props}>\n <TabsList aria-label={label}>\n {tabs.map((t) => (\n <TabsTrigger key={t.id} value={t.id}>\n {t.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {tabs.map((t) => (\n <TabsContent key={t.id} value={t.id}>\n {t.content}\n </TabsContent>\n ))}\n </TabsRoot>\n );\n}\n","// Client (a context). Radix Tabs does the roles (tablist, tab, tabpanel), the aria-selected / aria-controls wiring,\n// the roving focus (arrows, Home, End) and automatic activation: this file only holds the three looks.\nimport { Tabs as TabsPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const tabs = tv({\n slots: {\n root: \"flex gap-4 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row\",\n // One light glides from the active tab to the next (`before:`, placed by useSlidingIndicator); until it is placed\n // (server render), each trigger carries its own active style.\n list:\n \"group/tabs relative isolate flex shrink-0 data-[orientation=vertical]:flex-col \" +\n \"before:pointer-events-none before:absolute before:-z-10 before:opacity-0 before:transition-[translate,width,height,opacity] before:duration-300 \" +\n \"motion-reduce:before:transition-none data-[indicator=on]:before:opacity-100\",\n trigger:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40\",\n content: \"kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n variants: {\n variant: {\n /* The section of a page: a line under the list, the active tab underlined in the accent. */\n underline: {\n list:\n \"gap-1 border-border-default data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-r before:rounded-full before:bg-accent \" +\n \"data-[orientation=horizontal]:before:-bottom-px data-[orientation=horizontal]:before:left-0 data-[orientation=horizontal]:before:h-0.5 \" +\n \"data-[orientation=horizontal]:before:w-(--kz-ind-w) data-[orientation=horizontal]:before:translate-x-(--kz-ind-x) \" +\n \"data-[orientation=vertical]:before:-right-px data-[orientation=vertical]:before:top-0 data-[orientation=vertical]:before:w-0.5 \" +\n \"data-[orientation=vertical]:before:h-(--kz-ind-h) data-[orientation=vertical]:before:translate-y-(--kz-ind-y)\",\n trigger:\n \"relative rounded-md px-3 py-2.5 text-sm text-fg-secondary hover:text-fg data-[state=active]:text-fg \" +\n \"after:absolute after:rounded-full after:bg-transparent data-[state=active]:after:bg-accent \" +\n \"data-[orientation=horizontal]:after:inset-x-2 data-[orientation=horizontal]:after:-bottom-px data-[orientation=horizontal]:after:h-0.5 \" +\n \"data-[orientation=vertical]:justify-start data-[orientation=vertical]:after:inset-y-1.5 data-[orientation=vertical]:after:-right-px data-[orientation=vertical]:after:w-0.5 \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:after:bg-transparent\",\n },\n /* A view switch: equal segments in a track, the active one filled. */\n segmented: {\n list:\n \"inline-grid auto-cols-fr grid-flow-col gap-1 self-start rounded-xl border border-border-default bg-surface-1 p-1 data-[orientation=vertical]:grid-flow-row \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-lg before:bg-accent before:shadow-sm\",\n trigger:\n \"min-h-8 rounded-lg px-3 py-1.5 text-xs text-fg-secondary hover:bg-surface-2 hover:text-fg \" +\n \"data-[state=active]:bg-accent data-[state=active]:text-on-accent data-[state=active]:shadow-sm data-[state=active]:hover:bg-accent \" +\n \"transition-colors group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent group-data-[indicator=on]/tabs:data-[state=active]:shadow-none\",\n },\n /* Pills that scroll sideways on a phone: a feed's sections. */\n pills: {\n list:\n \"gap-1.5 overflow-x-auto overflow-y-hidden overscroll-x-contain pt-1 -mt-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:border before:border-accent before:bg-accent-soft\",\n trigger:\n \"h-9 rounded-full border border-border-default bg-surface-1 px-4 text-xs text-fg-secondary hover:border-border-strong hover:text-fg \" +\n \"data-[state=active]:border-accent data-[state=active]:bg-accent-soft data-[state=active]:text-fg \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:border-transparent group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent\",\n },\n },\n },\n defaultVariants: { variant: \"underline\" },\n});\n\nexport type TabsVariants = VariantProps<typeof tabs>;\ntype Variant = NonNullable<TabsVariants[\"variant\"]>;\n\nconst VariantContext = React.createContext<Variant>(\"underline\");\n\nexport type TabsRootProps = React.ComponentProps<typeof TabsPrimitive.Root> & {\n /** underline (the sections of a page) · segmented (a view switch) · pills (a feed's sections). */\n variant?: TabsVariants[\"variant\"];\n};\n\n/** `value`/`defaultValue` + `onValueChange`, `orientation` (horizontal by default), `variant` for the list. */\nexport function TabsRoot({ variant = \"underline\", className, ...props }: TabsRootProps) {\n return (\n <VariantContext.Provider value={variant}>\n <TabsPrimitive.Root data-variant={variant} className={tabs({ variant }).root({ className })} {...props} />\n </VariantContext.Provider>\n );\n}\n\n/** The tabs. Name it (`aria-label`) when no heading says what it switches. One light glides to the active tab. */\nexport function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n const variant = React.useContext(VariantContext);\n const { ref } = useSlidingIndicator<HTMLDivElement>({ item: \"[role=tab]\", active: \"[role=tab][data-state=active]\" });\n return <TabsPrimitive.List ref={ref} data-variant={variant} className={tabs({ variant }).list({ className })} {...props} />;\n}\n\nexport function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n const variant = React.useContext(VariantContext);\n return <TabsPrimitive.Trigger className={tabs({ variant }).trigger({ className })} {...props} />;\n}\n\nexport function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content className={tabs().content({ className })} {...props} />;\n}\n\n/** `Tabs.Root/List/Trigger/Content` — `variant` underline · segmented · pills on the root. */\nexport const Tabs = { Root: TabsRoot, List: TabsList, Trigger: TabsTrigger, Content: TabsContent };\n","// The shared sliding indicator (NavBar, Tabs): one element that glides from item to item instead of each item lighting\n// up on its own. It writes the target's box as CSS variables on the list (`--kz-ind-x/y/w/h`) and `data-indicator=\"on\"`\n// — no re-render, no animation frame: the glide is a CSS transition (none under reduced motion). Before hydration the\n// items keep their own active style, so nothing flashes.\nimport * as React from \"react\";\n\nconst useIsoLayoutEffect = typeof window === \"undefined\" ? React.useEffect : React.useLayoutEffect;\n\n/**\n * `item`: the selector of an item; `active`: of the current one, where the light rests; `prefer`: an item that, when\n * present, holds the light before the current one (the NavBar's open menu); `follow`: the light follows the pointer\n * and the focus — over anything that is not an item (an open menu's panel) it goes back to rest.\n */\nexport function useSlidingIndicator<T extends HTMLElement>({ item, active, prefer, follow = false }: { item: string; active: string; prefer?: string; follow?: boolean }) {\n const ref = React.useRef<T>(null);\n const place = React.useCallback((target: Element | null) => {\n const list = ref.current;\n if (!list) return;\n if (!(target instanceof HTMLElement) || !list.contains(target)) {\n list.removeAttribute(\"data-indicator\");\n return;\n }\n const a = target.getBoundingClientRect();\n const b = list.getBoundingClientRect();\n list.style.setProperty(\"--kz-ind-x\", `${a.left - b.left + list.scrollLeft}px`);\n list.style.setProperty(\"--kz-ind-y\", `${a.top - b.top + list.scrollTop}px`);\n list.style.setProperty(\"--kz-ind-w\", `${a.width}px`);\n list.style.setProperty(\"--kz-ind-h\", `${a.height}px`);\n list.setAttribute(\"data-indicator\", \"on\");\n }, []);\n const rest = React.useCallback(\n () => {\n const list = ref.current;\n // An item re-rendered under a resting pointer (a menu closing) keeps the light the pointer gave it.\n const hovered = follow ? list?.querySelector(`${item}:hover`) : null;\n place((prefer ? list?.querySelector(prefer) : null) ?? hovered ?? list?.querySelector(active) ?? null);\n },\n [place, active, prefer, item, follow],\n );\n const follow_ = React.useCallback((target: EventTarget) => {\n const hit = target instanceof Element ? target.closest(item) : null;\n if (hit && ref.current?.contains(hit)) place(hit);\n else rest();\n }, [item, place, rest]);\n\n useIsoLayoutEffect(() => {\n const list = ref.current;\n if (!list) return;\n rest();\n const resize = new ResizeObserver(rest);\n resize.observe(list);\n const changes = new MutationObserver(rest);\n changes.observe(list, { subtree: true, attributes: true, attributeFilter: [\"data-state\", \"aria-current\", \"data-active\"] });\n return () => {\n resize.disconnect();\n changes.disconnect();\n };\n }, [rest]);\n\n const handlers = follow\n ? {\n onPointerOver: (e: React.PointerEvent) => follow_(e.target),\n onPointerLeave: rest,\n onFocus: (e: React.FocusEvent) => follow_(e.target),\n onBlur: rest,\n }\n : {};\n return { ref, handlers };\n}\n","// Code → React nodes, from TanStack Highlight's tokens: spans with the `th-*` classes that blocks.css paints with the\n// tokens' text roles (≥ 4.5:1 on the code surface, both themes). No raw HTML: the nodes are elements and text.\nimport { type HighlightDecoration, type HighlightRenderNode, renderTokens } from \"@tanstack/highlight/core\";\nimport * as React from \"react\";\n\nimport { codeHighlighter } from \"./highlighter\";\n\n/** What an annotation says about its lines. */\nexport type AnnotationKind = \"highlight\" | \"added\" | \"removed\" | \"focus\" | \"dim\" | \"error\" | \"warning\";\n\n/** Lines of a sample set apart: one line (`3`) or a range (`[3, 5]`), counted from 1. */\nexport type CodeAnnotation = {\n lines: number | readonly [number, number];\n kind: AnnotationKind;\n};\n\nexport type HighlightOptions = {\n /** A number before every line. */\n lineNumbers?: boolean;\n /** Lines set apart: highlighted, added, removed, in focus (the others are dimmed), dimmed, error, warning. */\n annotations?: readonly CodeAnnotation[];\n};\n\nconst toReact = (node: HighlightRenderNode, key: number): React.ReactNode => {\n if (node.type === \"text\") return node.value;\n const data = Object.fromEntries(Object.entries(node.data ?? {}).map(([name, value]) => [`data-${name}`, value]));\n return React.createElement(\"span\", { key, className: node.classNames.join(\" \"), ...data }, node.children.map(toReact));\n};\n\n/** Splits `code` into text and coloured spans (`th-keyword`, `th-string`…), and into lines when numbered or annotated. */\nexport function highlight(code: string, language = \"text\", { lineNumbers, annotations }: HighlightOptions = {}): React.ReactNode[] {\n const { tokens } = codeHighlighter.tokenize(code, { lang: language });\n const decorations: HighlightDecoration[] = (annotations ?? []).map(({ lines, kind }) => ({ lines, className: `kz-line kz-line-${kind}`, data: { kind } }));\n return renderTokens(tokens, { lineNumbers, decorations }).map(toReact);\n}\n\n/** The language a sample is tokenized in (`bash` → `shell`, `xml` → `html`, unknown → `plaintext`). */\nexport function normalizeCodeLanguage(language?: string): string {\n return codeHighlighter.normalizeLanguage(language);\n}\n","// The highlighter of every code sample: TanStack Highlight (a deterministic, synchronous tokenizer — the same markup on\n// the server and on the client) with the grammars a Krizaka page shows. Each grammar is registered by hand: nothing\n// else is bundled. An unknown language is plain text, never an error.\nimport { createHighlighter } from \"@tanstack/highlight/core\";\nimport { css } from \"@tanstack/highlight/languages/css\";\nimport { diff } from \"@tanstack/highlight/languages/diff\";\nimport { env } from \"@tanstack/highlight/languages/env\";\nimport { html } from \"@tanstack/highlight/languages/html\";\nimport { java } from \"@tanstack/highlight/languages/java\";\nimport { js } from \"@tanstack/highlight/languages/js\";\nimport { json } from \"@tanstack/highlight/languages/json\";\nimport { jsx } from \"@tanstack/highlight/languages/jsx\";\nimport { kotlin } from \"@tanstack/highlight/languages/kotlin\";\nimport { plaintext } from \"@tanstack/highlight/languages/plaintext\";\nimport { shell } from \"@tanstack/highlight/languages/shell\";\nimport { ts } from \"@tanstack/highlight/languages/ts\";\nimport { tsx } from \"@tanstack/highlight/languages/tsx\";\nimport { yaml } from \"@tanstack/highlight/languages/yaml\";\n\n/** The languages a sample can be written in, with the names they answer to (`bash`, `xml`, `yml`, `kt`, `properties`…). */\nexport const codeHighlighter = createHighlighter({\n languages: [css, diff, { ...env, aliases: [...(env.aliases ?? []), \"properties\"] }, html, java, js, json, jsx, kotlin, plaintext, shell, ts, tsx, yaml],\n fallbackLanguage: \"plaintext\",\n});\n"],"mappings":"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","names":["React","React","React","jsx","jsx","tabs"]}
@@ -767,7 +767,7 @@ var datePicker = tv({
767
767
  clear: "absolute right-1.5 top-1/2 inline-flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-md text-fg-secondary hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:focus-ring",
768
768
  content: "w-auto rounded-2xl bg-sheen p-4 shadow-floating inset-shadow-edge",
769
769
  layout: "flex flex-col gap-4 sm:flex-row",
770
- presets: "flex gap-1.5 overflow-x-auto pb-1 sm:w-40 sm:flex-col sm:overflow-visible sm:border-r sm:border-border-subtle sm:pb-0 sm:pr-4",
770
+ presets: "flex gap-1.5 overflow-x-auto overflow-y-hidden pt-1 -mt-1 pb-1 sm:w-40 sm:flex-col sm:overflow-visible sm:border-r sm:border-border-subtle sm:pb-0 sm:pr-4",
771
771
  preset: "inline-flex shrink-0 items-center gap-2.5 whitespace-nowrap rounded-lg px-2.5 py-2 text-left text-xs font-semibold text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:focus-ring aria-pressed:bg-accent-soft aria-pressed:text-fg",
772
772
  presetNode: "node shrink-0 group-aria-pressed:node-lit",
773
773
  hint: "text-xs text-fg-secondary",
@@ -918,7 +918,7 @@ var dayStrip = tv({
918
918
  title: "text-sm font-semibold capitalize text-fg",
919
919
  navs: "flex gap-1.5",
920
920
  nav: "inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border-subtle bg-surface-2 bg-sheen text-fg-secondary inset-shadow-edge transition-colors hover:border-border-strong hover:text-fg focus-visible:outline-hidden focus-visible:focus-ring disabled:pointer-events-none disabled:opacity-35",
921
- track: "-mx-1 flex snap-x snap-mandatory gap-2 overflow-x-auto scroll-smooth px-1 py-1.5 [scrollbar-width:none] motion-reduce:scroll-auto [&::-webkit-scrollbar]:hidden",
921
+ track: "-mx-1 flex snap-x snap-mandatory gap-2 overflow-x-auto overflow-y-hidden scroll-smooth px-1 py-1.5 [scrollbar-width:none] motion-reduce:scroll-auto [&::-webkit-scrollbar]:hidden",
922
922
  day: "relative flex h-[4.5rem] w-14 shrink-0 snap-start flex-col items-center justify-center gap-0.5 rounded-2xl border border-border-default bg-surface-2 bg-sheen text-fg inset-shadow-edge transition-[background-color,border-color,box-shadow,transform] duration-150 hover:border-border-strong active:scale-95 motion-reduce:transition-none motion-reduce:active:scale-100 focus-visible:outline-hidden focus-visible:focus-ring aria-checked:border-transparent aria-checked:bg-accent aria-checked:bg-fill-shade aria-checked:text-on-accent aria-checked:shadow-glow aria-checked:inset-shadow-edge-fill disabled:cursor-not-allowed disabled:border-dashed disabled:bg-transparent disabled:bg-none disabled:text-fg-muted disabled:shadow-none",
923
923
  weekday: "text-[11px] font-semibold uppercase tracking-wider text-fg-secondary group-aria-checked:text-on-accent group-disabled:text-fg-muted",
924
924
  number: "text-lg font-semibold tabular-nums leading-none",