@krizaka/ui 3.8.0 → 3.9.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 (279) hide show
  1. package/README.md +10 -8
  2. package/dist/action-bar.js +2 -1
  3. package/dist/action-bar.js.map +1 -1
  4. package/dist/app-shell.d.ts +81 -3
  5. package/dist/app-shell.js +163 -35
  6. package/dist/app-shell.js.map +1 -1
  7. package/dist/audio-player.js +1 -1
  8. package/dist/badge.d.ts +36 -39
  9. package/dist/badge.js +11 -2
  10. package/dist/badge.js.map +1 -1
  11. package/dist/blocks.css +56 -4
  12. package/dist/button-BmCrLCq7.d.ts +114 -0
  13. package/dist/button.d.ts +48 -48
  14. package/dist/button.js +2 -1
  15. package/dist/card.d.ts +111 -111
  16. package/dist/card.js +10 -2
  17. package/dist/card.js.map +1 -1
  18. package/dist/chip.d.ts +24 -24
  19. package/dist/chip.js +10 -2
  20. package/dist/chip.js.map +1 -1
  21. package/dist/{chunk-UOMP6VOZ.js → chunk-276PTQMQ.js} +10 -4
  22. package/dist/chunk-276PTQMQ.js.map +1 -0
  23. package/dist/{chunk-Z6FUPB3Q.js → chunk-2NB27LM7.js} +11 -3
  24. package/dist/chunk-2NB27LM7.js.map +1 -0
  25. package/dist/chunk-2VNYHG4E.js +9 -0
  26. package/dist/chunk-2VNYHG4E.js.map +1 -0
  27. package/dist/{chunk-ND3L5VHT.js → chunk-5Z7FWCV2.js} +2 -2
  28. package/dist/{chunk-YH4LMWRU.js → chunk-7UCPGXKN.js} +11 -3
  29. package/dist/chunk-7UCPGXKN.js.map +1 -0
  30. package/dist/{chunk-AZPKXP3O.js → chunk-AFY35UCB.js} +6 -1
  31. package/dist/{chunk-AZPKXP3O.js.map → chunk-AFY35UCB.js.map} +1 -1
  32. package/dist/{chunk-LCZXS6AK.js → chunk-CKSHLSDH.js} +5 -5
  33. package/dist/chunk-CKSHLSDH.js.map +1 -0
  34. package/dist/chunk-D3T54RSL.js +11 -0
  35. package/dist/chunk-D3T54RSL.js.map +1 -0
  36. package/dist/{chunk-ZKVQGXLD.js → chunk-FKBHWS4N.js} +2 -2
  37. package/dist/{chunk-BRKMQ6JV.js → chunk-FZBWEDQI.js} +1 -23
  38. package/dist/chunk-FZBWEDQI.js.map +1 -0
  39. package/dist/{chunk-HCNOOPZE.js → chunk-KVDB4GXV.js} +2 -2
  40. package/dist/{chunk-RUPNPMP3.js → chunk-OWC2LZD2.js} +11 -3
  41. package/dist/chunk-OWC2LZD2.js.map +1 -0
  42. package/dist/{chunk-FDCMBWUU.js → chunk-REPTKUJ6.js} +4 -4
  43. package/dist/chunk-REPTKUJ6.js.map +1 -0
  44. package/dist/code-block.d.ts +32 -10
  45. package/dist/code-block.js +51 -43
  46. package/dist/code-block.js.map +1 -1
  47. package/dist/combobox.d.ts +3 -3
  48. package/dist/combobox.js +4 -3
  49. package/dist/command.js +3 -2
  50. package/dist/command.js.map +1 -1
  51. package/dist/component-page.js.map +1 -1
  52. package/dist/confirm-button.d.ts +1 -1
  53. package/dist/confirm-button.js +2 -1
  54. package/dist/confirm-button.js.map +1 -1
  55. package/dist/continue-prompt.js +11 -3
  56. package/dist/continue-prompt.js.map +1 -1
  57. package/dist/data-table.js +7 -6
  58. package/dist/data-table.js.map +1 -1
  59. package/dist/date-picker.js +1 -1
  60. package/dist/dialog.js +3 -2
  61. package/dist/dialog.js.map +1 -1
  62. package/dist/file-upload.d.ts +12 -1
  63. package/dist/file-upload.js +73 -89
  64. package/dist/file-upload.js.map +1 -1
  65. package/dist/filter-bar.js +3 -2
  66. package/dist/image-cropper.js +1 -1
  67. package/dist/list.js +1 -1
  68. package/dist/map.js.map +1 -1
  69. package/dist/markdown.d.ts +38 -0
  70. package/dist/markdown.js +150 -0
  71. package/dist/markdown.js.map +1 -0
  72. package/dist/match-dialog.js +2 -1
  73. package/dist/match-dialog.js.map +1 -1
  74. package/dist/media-capture.js +1 -1
  75. package/dist/native/markdown.d.ts +24 -0
  76. package/dist/native/markdown.js +200 -0
  77. package/dist/native/markdown.js.map +1 -0
  78. package/dist/native.d.ts +1 -7
  79. package/dist/native.js +357 -95
  80. package/dist/native.js.map +1 -1
  81. package/dist/recipes.d.ts +143 -0
  82. package/dist/recipes.js +180 -0
  83. package/dist/recipes.js.map +1 -0
  84. package/dist/search-field.js +2 -2
  85. package/dist/swipe-deck.js +1 -1
  86. package/dist/tag-input.js +4 -3
  87. package/dist/tag-input.js.map +1 -1
  88. package/dist/tag-selector.js +2 -1
  89. package/dist/tag-selector.js.map +1 -1
  90. package/dist/theme.d.ts +1 -1
  91. package/dist/theme.js +2 -1
  92. package/dist/theme.js.map +1 -1
  93. package/dist/tree-view.js +1 -1
  94. package/dist/vertical-video.js +2 -1
  95. package/dist/vertical-video.js.map +1 -1
  96. package/dist/video-player.js +1 -1
  97. package/dist/video-trimmer.js +1 -1
  98. package/dist/virtual.js +2 -2
  99. package/package.json +47 -16
  100. package/registry/achievement.json +1 -1
  101. package/registry/action-bar.json +1 -1
  102. package/registry/activity-feed.json +1 -1
  103. package/registry/alert.json +1 -1
  104. package/registry/app-shell.json +135 -12
  105. package/registry/argument-card.json +1 -1
  106. package/registry/audio-player.json +2 -2
  107. package/registry/auth-layout.json +1 -1
  108. package/registry/avatar.json +1 -1
  109. package/registry/badge.json +9 -3
  110. package/registry/button.json +7 -2
  111. package/registry/card-grid.json +1 -1
  112. package/registry/card.json +8 -3
  113. package/registry/catalogue-page.json +1 -1
  114. package/registry/changelog-page.json +1 -1
  115. package/registry/chat.json +1 -1
  116. package/registry/checkbox.json +1 -1
  117. package/registry/chip-link.json +1 -1
  118. package/registry/chip.json +9 -3
  119. package/registry/choice-grid.json +1 -1
  120. package/registry/code-block.json +65 -21
  121. package/registry/combobox.json +4 -3
  122. package/registry/command.json +1 -1
  123. package/registry/component-page.json +4 -4
  124. package/registry/confirm-button.json +1 -1
  125. package/registry/contact-page.json +1 -1
  126. package/registry/continue-prompt.json +1 -1
  127. package/registry/countdown.json +1 -1
  128. package/registry/cta-panel.json +1 -1
  129. package/registry/dashboard-layout.json +1 -1
  130. package/registry/data-table.json +2 -2
  131. package/registry/date-picker.json +3 -3
  132. package/registry/decision-list.json +1 -1
  133. package/registry/description-list.json +1 -1
  134. package/registry/detail-layout.json +1 -1
  135. package/registry/dialog.json +1 -1
  136. package/registry/docs-article-page.json +1 -1
  137. package/registry/docs-hub-page.json +1 -1
  138. package/registry/docs-layout.json +1 -1
  139. package/registry/dropdown-menu.json +1 -1
  140. package/registry/empty-state.json +1 -1
  141. package/registry/error-page.json +1 -1
  142. package/registry/examples/app-shell/console.d.ts +4 -0
  143. package/registry/examples/app-shell/console.js +93 -0
  144. package/registry/examples/app-shell/console.tsx +103 -0
  145. package/registry/examples/badge/native/dot.dark.png +0 -0
  146. package/registry/examples/badge/native/dot.light.png +0 -0
  147. package/registry/examples/badge/native/scrim.dark.png +0 -0
  148. package/registry/examples/badge/native/scrim.light.png +0 -0
  149. package/registry/examples/badge/native/tones.dark.png +0 -0
  150. package/registry/examples/badge/native/tones.light.png +0 -0
  151. package/registry/examples/card/native/default.dark.png +0 -0
  152. package/registry/examples/card/native/default.light.png +0 -0
  153. package/registry/examples/card/native/elevated.light.png +0 -0
  154. package/registry/examples/chip/native/multiple.dark.png +0 -0
  155. package/registry/examples/chip/native/multiple.light.png +0 -0
  156. package/registry/examples/chip/native/removable.dark.png +0 -0
  157. package/registry/examples/chip/native/removable.light.png +0 -0
  158. package/registry/examples/chip/native/single.dark.png +0 -0
  159. package/registry/examples/chip/native/single.light.png +0 -0
  160. package/registry/examples/chip/native/toggle.dark.png +0 -0
  161. package/registry/examples/chip/native/toggle.light.png +0 -0
  162. package/registry/examples/code-block/annotated.d.ts +4 -0
  163. package/registry/examples/code-block/annotated.js +31 -0
  164. package/registry/examples/code-block/annotated.tsx +26 -0
  165. package/registry/examples/component-page/button.tsx +1 -1
  166. package/registry/examples/form/native/amount.dark.png +0 -0
  167. package/registry/examples/form/native/amount.light.png +0 -0
  168. package/registry/examples/markdown/ai-stream.d.ts +4 -0
  169. package/registry/examples/markdown/ai-stream.js +31 -0
  170. package/registry/examples/markdown/ai-stream.tsx +32 -0
  171. package/registry/examples/markdown/basic.d.ts +4 -0
  172. package/registry/examples/markdown/basic.js +26 -0
  173. package/registry/examples/markdown/basic.tsx +22 -0
  174. package/registry/examples/markdown/native/ai-stream.d.ts +4 -0
  175. package/registry/examples/markdown/native/ai-stream.dark.png +0 -0
  176. package/registry/examples/markdown/native/ai-stream.js +17 -0
  177. package/registry/examples/markdown/native/ai-stream.light.png +0 -0
  178. package/registry/examples/markdown/native/ai-stream.tsx +17 -0
  179. package/registry/examples/markdown/native/basic.d.ts +4 -0
  180. package/registry/examples/markdown/native/basic.dark.png +0 -0
  181. package/registry/examples/markdown/native/basic.js +28 -0
  182. package/registry/examples/markdown/native/basic.light.png +0 -0
  183. package/registry/examples/markdown/native/basic.tsx +27 -0
  184. package/registry/examples/recipes/tone-chip.d.ts +4 -0
  185. package/registry/examples/recipes/tone-chip.js +46 -0
  186. package/registry/examples/recipes/tone-chip.tsx +32 -0
  187. package/registry/examples/screen/native/profile.dark.png +0 -0
  188. package/registry/examples/screen/native/profile.light.png +0 -0
  189. package/registry/examples/tag-selector/native/interests.dark.png +0 -0
  190. package/registry/examples/tag-selector/native/interests.light.png +0 -0
  191. package/registry/field.json +1 -1
  192. package/registry/file-upload.json +8 -3
  193. package/registry/filter-bar.json +1 -1
  194. package/registry/form.json +2 -2
  195. package/registry/gallery-page.json +1 -1
  196. package/registry/glow-card.json +1 -1
  197. package/registry/goal-gauge.json +1 -1
  198. package/registry/how-it-works-page.json +1 -1
  199. package/registry/image-cropper.json +2 -2
  200. package/registry/index.json +76 -16
  201. package/registry/iso.json +1 -1
  202. package/registry/kanban.json +1 -1
  203. package/registry/kbd.json +1 -1
  204. package/registry/landing-page.json +1 -1
  205. package/registry/landscape.json +1 -1
  206. package/registry/legal-page.json +1 -1
  207. package/registry/link-card.json +1 -1
  208. package/registry/list.json +2 -2
  209. package/registry/loader.json +1 -1
  210. package/registry/longform-page.json +1 -1
  211. package/registry/map.json +3 -3
  212. package/registry/markdown.json +266 -0
  213. package/registry/marketing-layout.json +1 -1
  214. package/registry/marquee.json +1 -1
  215. package/registry/mascot-quote.json +1 -1
  216. package/registry/mascot-state.json +1 -1
  217. package/registry/mascots.json +1 -1
  218. package/registry/match-dialog.json +1 -1
  219. package/registry/media-capture.json +2 -2
  220. package/registry/meter.json +1 -1
  221. package/registry/nav-bar.json +1 -1
  222. package/registry/number-ticker.json +1 -1
  223. package/registry/page-header.json +1 -1
  224. package/registry/page-hero.json +1 -1
  225. package/registry/page.json +1 -1
  226. package/registry/pagination.json +1 -1
  227. package/registry/photo-grid.json +1 -1
  228. package/registry/pointer-light.json +1 -1
  229. package/registry/popover.json +1 -1
  230. package/registry/pricing-page.json +1 -1
  231. package/registry/product-page.json +1 -1
  232. package/registry/profile-card.json +1 -1
  233. package/registry/progress.json +1 -1
  234. package/registry/promise-card.json +1 -1
  235. package/registry/radio-group.json +1 -1
  236. package/registry/recipes.json +99 -0
  237. package/registry/scroll-stage.json +1 -1
  238. package/registry/search-field.json +4 -3
  239. package/registry/section-backdrop.json +1 -1
  240. package/registry/separator.json +1 -1
  241. package/registry/settings-layout.json +1 -1
  242. package/registry/skeleton.json +1 -1
  243. package/registry/skip-link.json +1 -1
  244. package/registry/slider.json +1 -1
  245. package/registry/slot.json +1 -1
  246. package/registry/spinner.json +1 -1
  247. package/registry/split-view.json +1 -1
  248. package/registry/stage-banner.json +1 -1
  249. package/registry/stat.json +1 -1
  250. package/registry/status-page.json +1 -1
  251. package/registry/step-progress.json +1 -1
  252. package/registry/stepper.json +1 -1
  253. package/registry/swipe-deck.json +2 -2
  254. package/registry/switch.json +1 -1
  255. package/registry/tabs.json +1 -1
  256. package/registry/tag-input.json +2 -2
  257. package/registry/tag-selector.json +1 -1
  258. package/registry/terminal-replay.json +1 -1
  259. package/registry/theme.json +1 -1
  260. package/registry/toast.json +1 -1
  261. package/registry/toc.json +1 -1
  262. package/registry/tooltip.json +1 -1
  263. package/registry/tree-view.json +2 -2
  264. package/registry/verified-badge.json +1 -1
  265. package/registry/vertical-video.json +2 -2
  266. package/registry/video-player.json +2 -2
  267. package/registry/video-trimmer.json +2 -2
  268. package/registry/virtual.json +2 -2
  269. package/dist/button-BMAO7dKF.d.ts +0 -114
  270. package/dist/chunk-BRKMQ6JV.js.map +0 -1
  271. package/dist/chunk-FDCMBWUU.js.map +0 -1
  272. package/dist/chunk-LCZXS6AK.js.map +0 -1
  273. package/dist/chunk-RUPNPMP3.js.map +0 -1
  274. package/dist/chunk-UOMP6VOZ.js.map +0 -1
  275. package/dist/chunk-YH4LMWRU.js.map +0 -1
  276. package/dist/chunk-Z6FUPB3Q.js.map +0 -1
  277. /package/dist/{chunk-ND3L5VHT.js.map → chunk-5Z7FWCV2.js.map} +0 -0
  278. /package/dist/{chunk-ZKVQGXLD.js.map → chunk-FKBHWS4N.js.map} +0 -0
  279. /package/dist/{chunk-HCNOOPZE.js.map → chunk-KVDB4GXV.js.map} +0 -0
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  CheckGlyph,
4
4
  CopyGlyph
5
- } from "./chunk-AZPKXP3O.js";
5
+ } from "./chunk-AFY35UCB.js";
6
6
  import {
7
7
  cn
8
8
  } from "./chunk-G3ETON2A.js";
9
9
 
10
10
  // src/code-block/code-block.tsx
11
- import * as React3 from "react";
11
+ import * as React4 from "react";
12
12
 
13
13
  // src/tabs/tabs.tsx
14
14
  import { Tabs as TabsPrimitive } from "radix-ui";
@@ -107,44 +107,51 @@ function TabsContent({ className, ...props }) {
107
107
  return /* @__PURE__ */ jsx(TabsPrimitive.Content, { className: tabs().content({ className }), ...props });
108
108
  }
109
109
 
110
- // src/code-block/highlight.tsx
111
- import { jsx as jsx2 } from "react/jsx-runtime";
112
- var CLASS = { comment: "kz-tk-comment", string: "kz-tk-string", annotation: "kz-tk-annotation", tag: "kz-tk-tag", keyword: "kz-tk-keyword" };
113
- var KEYWORDS = "public|private|protected|final|static|class|interface|record|extends|implements|return|new|try|catch|throw|throws|if|else|void|import|from|export|function|const|let|var|val|fun|true|false|null|this|default|async|await|type";
114
- var TOKEN = new RegExp(
115
- [
116
- String.raw`(?<comment>\/\/[^\n]*|\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->|(?:^|(?<=[\s]))#[^\n]*)`,
117
- String.raw`(?<string>"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|\x60(?:[^\x60\\]|\\.)*\x60)`,
118
- String.raw`(?<annotation>@[A-Za-z][\w.]*)`,
119
- String.raw`(?<tag><\/?[A-Za-z][\w.:-]*|\/?>)`,
120
- String.raw`(?<keyword>\b(?:${KEYWORDS})\b)`
121
- ].join("|"),
122
- "g"
123
- );
124
- function highlight(code, language) {
125
- const out = [];
126
- let last = 0;
127
- for (const m of code.matchAll(TOKEN)) {
128
- const kind = Object.entries(m.groups ?? {}).find(([, v]) => v !== void 0)?.[0];
129
- if (!kind) continue;
130
- if (kind === "tag" && !/^(xml|html|svg|jsx|tsx)$/.test(language)) continue;
131
- if (kind === "comment" && m[0].startsWith("#") && /^(css|scss|tsx?|jsx?|java|kotlin|kt)$/.test(language)) continue;
132
- if (kind === "string" && m[0].startsWith("'") && /^(xml|html|kotlin|kt|java)$/.test(language)) continue;
133
- if (m.index > last) out.push(code.slice(last, m.index));
134
- out.push(
135
- /* @__PURE__ */ jsx2("span", { className: CLASS[kind], children: m[0] }, m.index)
136
- );
137
- last = m.index + m[0].length;
138
- }
139
- if (last < code.length) out.push(code.slice(last));
140
- return out;
110
+ // src/code-block/tokens.tsx
111
+ import { renderTokens } from "@tanstack/highlight/core";
112
+ import * as React3 from "react";
113
+
114
+ // src/code-block/highlighter.ts
115
+ import { createHighlighter } from "@tanstack/highlight/core";
116
+ import { css } from "@tanstack/highlight/languages/css";
117
+ import { diff } from "@tanstack/highlight/languages/diff";
118
+ import { env } from "@tanstack/highlight/languages/env";
119
+ import { html } from "@tanstack/highlight/languages/html";
120
+ import { java } from "@tanstack/highlight/languages/java";
121
+ import { js } from "@tanstack/highlight/languages/js";
122
+ import { json } from "@tanstack/highlight/languages/json";
123
+ import { jsx as jsx2 } from "@tanstack/highlight/languages/jsx";
124
+ import { kotlin } from "@tanstack/highlight/languages/kotlin";
125
+ import { plaintext } from "@tanstack/highlight/languages/plaintext";
126
+ import { shell } from "@tanstack/highlight/languages/shell";
127
+ import { ts } from "@tanstack/highlight/languages/ts";
128
+ import { tsx } from "@tanstack/highlight/languages/tsx";
129
+ import { yaml } from "@tanstack/highlight/languages/yaml";
130
+ var codeHighlighter = createHighlighter({
131
+ languages: [css, diff, { ...env, aliases: [...env.aliases ?? [], "properties"] }, html, java, js, json, jsx2, kotlin, plaintext, shell, ts, tsx, yaml],
132
+ fallbackLanguage: "plaintext"
133
+ });
134
+
135
+ // src/code-block/tokens.tsx
136
+ var toReact = (node, key) => {
137
+ if (node.type === "text") return node.value;
138
+ const data = Object.fromEntries(Object.entries(node.data ?? {}).map(([name, value]) => [`data-${name}`, value]));
139
+ return React3.createElement("span", { key, className: node.classNames.join(" "), ...data }, node.children.map(toReact));
140
+ };
141
+ function highlight(code, language = "text", { lineNumbers, annotations } = {}) {
142
+ const { tokens } = codeHighlighter.tokenize(code, { lang: language });
143
+ const decorations = (annotations ?? []).map(({ lines, kind }) => ({ lines, className: `kz-line kz-line-${kind}`, data: { kind } }));
144
+ return renderTokens(tokens, { lineNumbers, decorations }).map(toReact);
145
+ }
146
+ function normalizeCodeLanguage(language) {
147
+ return codeHighlighter.normalizeLanguage(language);
141
148
  }
142
149
 
143
150
  // src/code-block/code-block.tsx
144
151
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
145
- function CodeBlock({ code, language = "text", file, copyLabel, copiedLabel, highlight: colour = true, onCopy, className, ...props }) {
146
- const [copied, setCopied] = React3.useState(false);
147
- React3.useEffect(() => {
152
+ function CodeBlock({ code, language = "text", file, copyLabel, copiedLabel, highlight: colour = true, lineNumbers, annotations, onCopy, className, ...props }) {
153
+ const [copied, setCopied] = React4.useState(false);
154
+ React4.useEffect(() => {
148
155
  if (!copied) return;
149
156
  const t = setTimeout(() => setCopied(false), 1800);
150
157
  return () => clearTimeout(t);
@@ -154,17 +161,17 @@ function CodeBlock({ code, language = "text", file, copyLabel, copiedLabel, high
154
161
  onCopy?.();
155
162
  });
156
163
  return /* @__PURE__ */ jsxs("figure", { className: cn("kz-code", className), ...props, children: [
157
- /* @__PURE__ */ jsxs("figcaption", { className: "kz-code-bar", children: [
164
+ file || language !== "text" || copyLabel ? /* @__PURE__ */ jsxs("figcaption", { className: "kz-code-bar", children: [
158
165
  /* @__PURE__ */ jsxs("span", { className: "kz-code-file", children: [
159
166
  language !== "text" && /* @__PURE__ */ jsx3("span", { className: "kz-code-lang", children: language }),
160
167
  file
161
168
  ] }),
162
- /* @__PURE__ */ jsxs("button", { type: "button", className: "kz-code-copy", onClick: copy, "data-copied": copied ? "" : void 0, children: [
169
+ copyLabel ? /* @__PURE__ */ jsxs("button", { type: "button", className: "kz-code-copy", onClick: copy, "data-copied": copied ? "" : void 0, children: [
163
170
  copied ? /* @__PURE__ */ jsx3(CheckGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx3(CopyGlyph, { className: "h-3.5 w-3.5" }),
164
- /* @__PURE__ */ jsx3("span", { "aria-live": "polite", children: copied ? copiedLabel : copyLabel })
165
- ] })
166
- ] }),
167
- /* @__PURE__ */ jsx3("pre", { tabIndex: 0, children: /* @__PURE__ */ jsx3("code", { "data-language": language, children: colour ? highlight(code, language) : code }) })
171
+ /* @__PURE__ */ jsx3("span", { "aria-live": "polite", children: copied ? copiedLabel ?? copyLabel : copyLabel })
172
+ ] }) : null
173
+ ] }) : null,
174
+ /* @__PURE__ */ jsx3("pre", { tabIndex: 0, className: lineNumbers ? "th-code--line-numbers" : void 0, "data-focus": annotations?.some((a) => a.kind === "focus") ? "" : void 0, children: /* @__PURE__ */ jsx3("code", { "data-language": language, children: colour ? highlight(code, language, { lineNumbers, annotations }) : code }) })
168
175
  ] });
169
176
  }
170
177
  function CodeTabs({ label, tabs: tabs2, defaultValue, className, ...props }) {
@@ -176,6 +183,7 @@ function CodeTabs({ label, tabs: tabs2, defaultValue, className, ...props }) {
176
183
  export {
177
184
  CodeBlock,
178
185
  CodeTabs,
179
- highlight
186
+ highlight,
187
+ normalizeCodeLanguage
180
188
  };
181
189
  //# sourceMappingURL=code-block.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/code-block/code-block.tsx","../src/tabs/tabs.tsx","../src/sliding-indicator.ts","../src/code-block/highlight.tsx"],"sourcesContent":["// Client (the copy button, the tabs). A sample of code (blocks.css): its language and its file name, the code\n// highlighted (it scrolls sideways, never shrinks, and takes the keyboard's focus to scroll), a copy button that says\n// it copied in a polite 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 { highlight } from \"./highlight\";\n\nexport type CodeBlockProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The code, as it is copied. */\n code: string;\n /** Its language, shown as a tag and used by the highlighter: `xml`, `kotlin`, `ts`, `bash`, `yaml`… */\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. */\n copyLabel: string;\n /** What the button says once the code is copied (announced politely). */\n copiedLabel: string;\n /**\n * Colours comments, strings, annotations, tags and keywords (the tokens' roles).\n * @default true\n */\n highlight?: boolean;\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, 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 <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 <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}</span>\n </button>\n </figcaption>\n <pre tabIndex={0}>\n <code data-language={language}>{colour ? highlight(code, language) : 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","// A small highlighter for the samples of a page (blocks.css `.kz-tk-*`): comments, strings, annotations, XML tags and\n// keywords — no highlighter in the bundle, no colour outside the tokens (each ≥ 4.5:1 on the code surface in both\n// themes). It colours what helps reading a sample; it is not a parser.\nimport type * as React from \"react\";\n\nconst CLASS = { comment: \"kz-tk-comment\", string: \"kz-tk-string\", annotation: \"kz-tk-annotation\", tag: \"kz-tk-tag\", keyword: \"kz-tk-keyword\" } as const;\ntype Kind = keyof typeof CLASS;\n\nconst KEYWORDS =\n \"public|private|protected|final|static|class|interface|record|extends|implements|return|new|try|catch|throw|throws|if|else|void|import|from|export|function|const|let|var|val|fun|true|false|null|this|default|async|await|type\";\n\nconst TOKEN = new RegExp(\n [\n String.raw`(?<comment>\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/|<!--[\\s\\S]*?-->|(?:^|(?<=[\\s]))#[^\\n]*)`,\n String.raw`(?<string>\"(?:[^\"\\\\\\n]|\\\\.)*\"|'(?:[^'\\\\\\n]|\\\\.)*'|\\x60(?:[^\\x60\\\\]|\\\\.)*\\x60)`,\n String.raw`(?<annotation>@[A-Za-z][\\w.]*)`,\n String.raw`(?<tag><\\/?[A-Za-z][\\w.:-]*|\\/?>)`,\n String.raw`(?<keyword>\\b(?:${KEYWORDS})\\b)`,\n ].join(\"|\"),\n \"g\",\n);\n\n/** Splits `code` into text and coloured spans. A `#` after a space starts a comment (shell, YAML, properties), not in CSS or code. */\nexport function highlight(code: string, language: string): React.ReactNode[] {\n const out: React.ReactNode[] = [];\n let last = 0;\n for (const m of code.matchAll(TOKEN)) {\n const kind = Object.entries(m.groups ?? {}).find(([, v]) => v !== undefined)?.[0] as Kind | undefined;\n if (!kind) continue;\n if (kind === \"tag\" && !/^(xml|html|svg|jsx|tsx)$/.test(language)) continue;\n if (kind === \"comment\" && m[0].startsWith(\"#\") && /^(css|scss|tsx?|jsx?|java|kotlin|kt)$/.test(language)) continue;\n if (kind === \"string\" && m[0].startsWith(\"'\") && /^(xml|html|kotlin|kt|java)$/.test(language)) continue;\n if (m.index > last) out.push(code.slice(last, m.index));\n out.push(\n <span key={m.index} className={CLASS[kind]}>\n {m[0]}\n </span>,\n );\n last = m.index + m[0].length;\n }\n if (last < code.length) out.push(code.slice(last));\n return out;\n}\n"],"mappings":"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","names":["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 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":";;;;;;;;;;AAKA,YAAYA,YAAW;;;ACHvB,SAAS,QAAQ,qBAAqB;AACtC,YAAYC,YAAW;AACvB,SAAS,UAA6B;;;ACAtC,YAAY,WAAW;AAEvB,IAAM,qBAAqB,OAAO,WAAW,cAAoB,kBAAkB;AAE5E,SAAS,oBAA2C,EAAE,MAAM,QAAQ,SAAS,MAAM,GAAuD;AAC/I,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,kBAAY,MAAM,MAAM,IAAI,SAAS,cAAc,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,MAAM,CAAC;AAEvG,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,MAAO,EAAE,OAAmB,QAAQ,IAAI,CAAC;AAAA,IACnF,gBAAgB;AAAA,IAChB,SAAS,CAAC,MAAwB,MAAO,EAAE,OAAmB,QAAQ,IAAI,CAAC;AAAA,IAC3E,QAAQ;AAAA,EACV,IACA,CAAC;AACL,SAAO,EAAE,KAAK,SAAS;AACzB;;;AD6BM;AAvEC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,MAAM;AAAA;AAAA;AAAA,IAGN,MACE;AAAA,IAGF,SACE;AAAA,IAEF,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA;AAAA,MAEP,WAAW;AAAA,QACT,MACE;AAAA,QAKF,SACE;AAAA,MAKJ;AAAA;AAAA,MAEA,WAAW;AAAA,QACT,MACE;AAAA,QAEF,SACE;AAAA,MAGJ;AAAA;AAAA,MAEA,OAAO;AAAA,QACL,MACE;AAAA,QAGF,SACE;AAAA,MAGJ;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,YAAY;AAC1C,CAAC;AAKD,IAAM,iBAAuB,qBAAuB,WAAW;AAQxD,SAAS,SAAS,EAAE,UAAU,aAAa,WAAW,GAAG,MAAM,GAAkB;AACtF,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC9B,8BAAC,cAAc,MAAd,EAAmB,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GAC1G;AAEJ;AAGO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAoD;AACjG,QAAM,UAAgB,kBAAW,cAAc;AAC/C,QAAM,EAAE,IAAI,IAAI,oBAAoC,EAAE,MAAM,cAAc,QAAQ,gCAAgC,CAAC;AACnH,SAAO,oBAAC,cAAc,MAAd,EAAmB,KAAU,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC3H;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,QAAM,UAAgB,kBAAW,cAAc;AAC/C,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAChG;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrF;;;AEhGA,SAA6D,oBAAoB;AACjF,YAAYC,YAAW;;;ACAvB,SAAS,yBAAyB;AAClC,SAAS,WAAW;AACpB,SAAS,YAAY;AACrB,SAAS,WAAW;AACpB,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB,SAAS,UAAU;AACnB,SAAS,YAAY;AACrB,SAAS,OAAAC,YAAW;AACpB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AACtB,SAAS,UAAU;AACnB,SAAS,WAAW;AACpB,SAAS,YAAY;AAGd,IAAM,kBAAkB,kBAAkB;AAAA,EAC/C,WAAW,CAAC,KAAK,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,GAAI,IAAI,WAAW,CAAC,GAAI,YAAY,EAAE,GAAG,MAAM,MAAM,IAAI,MAAMA,MAAK,QAAQ,WAAW,OAAO,IAAI,KAAK,IAAI;AAAA,EACtJ,kBAAkB;AACpB,CAAC;;;ADAD,IAAM,UAAU,CAAC,MAA2B,QAAiC;AAC3E,MAAI,KAAK,SAAS,OAAQ,QAAO,KAAK;AACtC,QAAM,OAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,IAAI,IAAI,KAAK,CAAC,CAAC;AAC/G,SAAa,qBAAc,QAAQ,EAAE,KAAK,WAAW,KAAK,WAAW,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC;AACvH;AAGO,SAAS,UAAU,MAAc,WAAW,QAAQ,EAAE,aAAa,YAAY,IAAsB,CAAC,GAAsB;AACjI,QAAM,EAAE,OAAO,IAAI,gBAAgB,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC;AACpE,QAAM,eAAsC,eAAe,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,EAAE,OAAO,WAAW,mBAAmB,IAAI,IAAI,MAAM,EAAE,KAAK,EAAE,EAAE;AACzJ,SAAO,aAAa,QAAQ,EAAE,aAAa,YAAY,CAAC,EAAE,IAAI,OAAO;AACvE;AAGO,SAAS,sBAAsB,UAA2B;AAC/D,SAAO,gBAAgB,kBAAkB,QAAQ;AACnD;;;AHiBU,SAC0B,OAAAC,MAD1B;AAhBH,SAAS,UAAU,EAAE,MAAM,WAAW,QAAQ,MAAM,WAAW,aAAa,WAAW,SAAS,MAAM,aAAa,aAAa,QAAQ,WAAW,GAAG,MAAM,GAAmB;AACpL,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAS,KAAK;AAChD,EAAM,iBAAU,MAAM;AACpB,QAAI,CAAC,OAAQ;AACb,UAAM,IAAI,WAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AACjD,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,OAAO,MACX,UAAU,WAAW,UAAU,IAAI,EAAE,KAAK,MAAM;AAC9C,cAAU,IAAI;AACd,aAAS;AAAA,EACX,CAAC;AACH,SACE,qBAAC,YAAO,WAAW,GAAG,WAAW,SAAS,GAAI,GAAG,OAC9C;AAAA,YAAQ,aAAa,UAAU,YAC9B,qBAAC,gBAAW,WAAU,eACpB;AAAA,2BAAC,UAAK,WAAU,gBACb;AAAA,qBAAa,UAAU,gBAAAA,KAAC,UAAK,WAAU,gBAAgB,oBAAS;AAAA,QAChE;AAAA,SACH;AAAA,MACC,YACC,qBAAC,YAAO,MAAK,UAAS,WAAU,gBAAe,SAAS,MAAM,eAAa,SAAS,KAAK,QACtF;AAAA,iBAAS,gBAAAA,KAAC,cAAW,WAAU,eAAc,IAAK,gBAAAA,KAAC,aAAU,WAAU,eAAc;AAAA,QACtF,gBAAAA,KAAC,UAAK,aAAU,UAAU,mBAAU,eAAe,YAAa,WAAU;AAAA,SAC5E,IACE;AAAA,OACN,IACE;AAAA,IACJ,gBAAAA,KAAC,SAAI,UAAU,GAAG,WAAW,cAAc,0BAA0B,QAAW,cAAY,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI,KAAK,QAC9I,0BAAAA,KAAC,UAAK,iBAAe,UAAW,mBAAS,UAAU,MAAM,UAAU,EAAE,aAAa,YAAY,CAAC,IAAI,MAAK,GAC1G;AAAA,KACF;AAEJ;AAYO,SAAS,SAAS,EAAE,OAAO,MAAAC,OAAM,cAAc,WAAW,GAAG,MAAM,GAAkB;AAC1F,SACE,qBAAC,YAAS,cAAc,gBAAgBA,MAAK,CAAC,GAAG,IAAI,SAAQ,aAAY,WAAW,GAAG,gBAAgB,SAAS,GAAI,GAAG,OACrH;AAAA,oBAAAD,KAAC,YAAS,cAAY,OACnB,UAAAC,MAAK,IAAI,CAAC,MACT,gBAAAD,KAAC,eAAuB,OAAO,EAAE,IAC9B,YAAE,SADa,EAAE,EAEpB,CACD,GACH;AAAA,IACCC,MAAK,IAAI,CAAC,MACT,gBAAAD,KAAC,eAAuB,OAAO,EAAE,IAC9B,YAAE,WADa,EAAE,EAEpB,CACD;AAAA,KACH;AAEJ;","names":["React","React","React","jsx","jsx","tabs"]}
@@ -4,6 +4,7 @@ import * as React from 'react';
4
4
  declare const combobox: tailwind_variants.TVReturnType<{
5
5
  [key: string]: {
6
6
  [key: string]: tailwind_variants.ClassValue | {
7
+ description?: tailwind_variants.ClassValue;
7
8
  input?: tailwind_variants.ClassValue;
8
9
  label?: tailwind_variants.ClassValue;
9
10
  option?: tailwind_variants.ClassValue;
@@ -12,7 +13,6 @@ declare const combobox: tailwind_variants.TVReturnType<{
12
13
  hint?: tailwind_variants.ClassValue;
13
14
  root?: tailwind_variants.ClassValue;
14
15
  check?: tailwind_variants.ClassValue;
15
- description?: tailwind_variants.ClassValue;
16
16
  error?: tailwind_variants.ClassValue;
17
17
  control?: tailwind_variants.ClassValue;
18
18
  icon?: tailwind_variants.ClassValue;
@@ -21,6 +21,7 @@ declare const combobox: tailwind_variants.TVReturnType<{
21
21
  } | {
22
22
  [x: string]: {
23
23
  [x: string]: tailwind_variants.ClassValue | {
24
+ description?: tailwind_variants.ClassValue;
24
25
  input?: tailwind_variants.ClassValue;
25
26
  label?: tailwind_variants.ClassValue;
26
27
  option?: tailwind_variants.ClassValue;
@@ -29,7 +30,6 @@ declare const combobox: tailwind_variants.TVReturnType<{
29
30
  hint?: tailwind_variants.ClassValue;
30
31
  root?: tailwind_variants.ClassValue;
31
32
  check?: tailwind_variants.ClassValue;
32
- description?: tailwind_variants.ClassValue;
33
33
  error?: tailwind_variants.ClassValue;
34
34
  control?: tailwind_variants.ClassValue;
35
35
  icon?: tailwind_variants.ClassValue;
@@ -51,6 +51,7 @@ declare const combobox: tailwind_variants.TVReturnType<{
51
51
  }, undefined, {
52
52
  [key: string]: {
53
53
  [key: string]: tailwind_variants.ClassValue | {
54
+ description?: tailwind_variants.ClassValue;
54
55
  input?: tailwind_variants.ClassValue;
55
56
  label?: tailwind_variants.ClassValue;
56
57
  option?: tailwind_variants.ClassValue;
@@ -59,7 +60,6 @@ declare const combobox: tailwind_variants.TVReturnType<{
59
60
  hint?: tailwind_variants.ClassValue;
60
61
  root?: tailwind_variants.ClassValue;
61
62
  check?: tailwind_variants.ClassValue;
62
- description?: tailwind_variants.ClassValue;
63
63
  error?: tailwind_variants.ClassValue;
64
64
  control?: tailwind_variants.ClassValue;
65
65
  icon?: tailwind_variants.ClassValue;
package/dist/combobox.js CHANGED
@@ -3,10 +3,11 @@ import {
3
3
  Combobox,
4
4
  combobox,
5
5
  comboboxLabels
6
- } from "./chunk-LCZXS6AK.js";
7
- import "./chunk-YH4LMWRU.js";
6
+ } from "./chunk-CKSHLSDH.js";
7
+ import "./chunk-7UCPGXKN.js";
8
+ import "./chunk-D3T54RSL.js";
8
9
  import "./chunk-ZIXB33X7.js";
9
- import "./chunk-BRKMQ6JV.js";
10
+ import "./chunk-FZBWEDQI.js";
10
11
  import "./chunk-CPA5CF35.js";
11
12
  export {
12
13
  Combobox,
package/dist/command.js CHANGED
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
  import {
3
3
  DialogContent
4
- } from "./chunk-ND3L5VHT.js";
5
- import "./chunk-RUPNPMP3.js";
4
+ } from "./chunk-5Z7FWCV2.js";
5
+ import "./chunk-OWC2LZD2.js";
6
+ import "./chunk-D3T54RSL.js";
6
7
  import "./chunk-WEVYKZIF.js";
7
8
  import {
8
9
  cn
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/command/command.tsx"],"sourcesContent":["// Client. A command palette on cmdk: the combobox / listbox roles, the active option (aria-activedescendant), the\n// arrows, Home / End, Enter, and the filtering (turn it off with `shouldFilter={false}` when the server searches).\n// `CommandDialog` puts it in the platform's Dialog. Words arrive as props.\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { DialogContent, type DialogContentProps } from \"../dialog/dialog\";\n\nexport const command = tv({\n slots: {\n root: \"flex h-full w-full flex-col overflow-hidden bg-surface-1 text-fg\",\n inputWrap: \"flex items-center gap-3 border-b border-border-default px-4\",\n icon: \"h-5 w-5 shrink-0 text-fg-secondary\",\n input:\n \"h-13 w-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted disabled:cursor-not-allowed disabled:opacity-50 sm:text-base\",\n list: \"max-h-[min(60dvh,26rem)] scroll-py-2 overflow-y-auto overscroll-contain p-2 [&:not(:has([cmdk-item]))]:p-0\",\n empty: \"px-3 py-8 text-center text-sm text-fg-secondary\",\n loading: \"px-3 py-6 text-center text-sm text-fg-secondary\",\n group:\n \"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pb-1.5 [&_[cmdk-group-heading]]:pt-3 [&_[cmdk-group-heading]]:text-xs \" +\n \"[&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-fg-secondary\",\n item:\n \"relative flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2.5 text-sm text-fg outline-hidden transition-colors \" +\n \"before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-transparent \" +\n \"data-[selected=true]:bg-surface-2 data-[selected=true]:before:bg-accent data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-40\",\n separator: \"-mx-2 my-1 h-px bg-border-subtle\",\n shortcut: \"ml-auto text-xs tracking-widest text-fg-secondary\",\n },\n});\nconst s = command();\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </svg>\n );\n}\n\nexport type CommandRootProps = React.ComponentProps<typeof CommandPrimitive> & {\n /** The accessible name of the palette — passed translated (\"Search\", \"Commands\"). */\n label: string;\n};\n\n/** The palette: `value` / `onValueChange` (the active item), `shouldFilter`, `filter`, `loop`. */\nexport function CommandRoot({ className, ...props }: CommandRootProps) {\n return <CommandPrimitive className={s.root({ className })} {...props} />;\n}\n\nexport type CommandInputProps = Omit<React.ComponentProps<typeof CommandPrimitive.Input>, \"placeholder\"> & {\n /** What to type — passed translated. The input is named by the palette's `label`. */\n placeholder: string;\n /** After the input, inside the bar: a spinner, a clear button. */\n trailing?: React.ReactNode;\n};\n\n/** The search field (`value` / `onValueChange` for the query), with a magnifier. */\nexport function CommandInput({ className, placeholder, trailing, ...props }: CommandInputProps) {\n return (\n <div className={s.inputWrap()} cmdk-input-wrapper=\"\">\n <SearchIcon className={s.icon()} />\n <CommandPrimitive.Input placeholder={placeholder} className={s.input({ className })} {...props} />\n {trailing}\n </div>\n );\n}\n\n// Set inside `Command.List`: a listbox may only hold options and groups (axe `aria-required-children`), so the empty\n// message must live beside it, not in it.\nconst InsideList = React.createContext(false);\n\nexport type CommandListProps = React.ComponentProps<typeof CommandPrimitive.List> & {\n /** The accessible name of the list of results — passed translated (\"Suggestions\", \"Results\"). */\n label: string;\n /**\n * Shown when nothing matches — passed translated. Rendered after the listbox, never inside it: an empty listbox is\n * valid, a listbox holding text is not.\n */\n emptyLabel?: React.ReactNode;\n};\n\nexport function CommandList({ className, emptyLabel, children, ...props }: CommandListProps) {\n return (\n <>\n <CommandPrimitive.List className={s.list({ className })} {...props}>\n <InsideList.Provider value>{children}</InsideList.Provider>\n </CommandPrimitive.List>\n {emptyLabel === undefined ? null : <CommandEmpty emptyLabel={emptyLabel} />}\n </>\n );\n}\n\nexport type CommandEmptyProps = Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, \"children\"> & {\n /** Shown when nothing matches — passed translated. */\n emptyLabel: React.ReactNode;\n};\n\n/**\n * Shown by cmdk only when no item matches. Place it beside `Command.List` (or pass `emptyLabel` to the list), never\n * inside it: inside, it is rendered as before but warns in development — the listbox then holds text, which axe\n * refuses (`aria-required-children`).\n */\nexport function CommandEmpty({ className, emptyLabel, ...props }: CommandEmptyProps) {\n const inside = React.useContext(InsideList);\n React.useEffect(() => {\n if (inside && typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\") {\n console.warn(\"@krizaka/ui/command: <Command.Empty> inside <Command.List> breaks the listbox (axe aria-required-children). Pass `emptyLabel` to <Command.List> instead.\");\n }\n }, [inside]);\n return (\n <CommandPrimitive.Empty className={s.empty({ className })} {...props}>\n {emptyLabel}\n </CommandPrimitive.Empty>\n );\n}\n\n/** While results load (`label` is announced). */\nexport function CommandLoading({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Loading>) {\n return <CommandPrimitive.Loading className={s.loading({ className })} {...props} />;\n}\n\n/** A group of items under a `heading`. */\nexport function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return <CommandPrimitive.Group className={s.group({ className })} {...props} />;\n}\n\n/** An option: `onSelect` on Enter or click, `value` and `keywords` for the filter, `disabled`. */\nexport function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return <CommandPrimitive.Item className={s.item({ className })} {...props} />;\n}\n\n/** A line between groups. Decorative (`role=\"none\"`): cmdk's own separator is a role a listbox may not hold (axe). */\nexport function CommandSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div role=\"none\" className={s.separator({ className })} {...props} />;\n}\n\n/** A keyboard hint at the end of an item. */\nexport function CommandShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n return <span className={s.shortcut({ className })} {...props} />;\n}\n\n/** `Command.Root/Input/List/Empty/Loading/Group/Item/Separator/Shortcut`. */\nexport const Command = {\n Root: CommandRoot,\n Input: CommandInput,\n List: CommandList,\n Empty: CommandEmpty,\n Loading: CommandLoading,\n Group: CommandGroup,\n Item: CommandItem,\n Separator: CommandSeparator,\n Shortcut: CommandShortcut,\n};\n\nexport type CommandDialogProps = Omit<CommandRootProps, \"title\"> & {\n /** Open or closed (controlled), with `onOpenChange`. */\n open?: boolean;\n /** Open at first, uncontrolled. */\n defaultOpen?: boolean;\n /** Called when it opens or closes (Escape, a click outside, a shortcut of the product). */\n onOpenChange?: (open: boolean) => void;\n /** Under the palette, inside the dialog: shortcuts, a \"see all results\" link. */\n footer?: React.ReactNode;\n /** Passed to `Dialog.Content`: `size`, `container`, `className` of the dialog. */\n contentProps?: Omit<Extract<DialogContentProps, { hideClose: true }>, \"hideClose\" | \"children\" | \"placement\">;\n};\n\n/**\n * The palette in a dialog (Radix: focus trap, Escape, focus return). The dialog is named by `label`; it has no close\n * button — Escape and a click outside close it — and the input takes the focus when it opens.\n */\nexport function CommandDialog({ open, defaultOpen, onOpenChange, footer, contentProps, label, className, children, ...props }: CommandDialogProps) {\n const { className: contentClassName, ...content } = contentProps ?? {};\n return (\n <DialogPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <DialogContent\n hideClose\n size=\"lg\"\n aria-describedby={undefined}\n className={cn(\"top-[12dvh] translate-y-0 sm:top-[14dvh]\", contentClassName)}\n {...content}\n >\n <DialogPrimitive.Title className=\"sr-only\">{label}</DialogPrimitive.Title>\n <CommandRoot label={label} className={className} {...props}>\n {children}\n </CommandRoot>\n {footer}\n </DialogContent>\n </DialogPrimitive.Root>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/command/command.tsx"],"sourcesContent":["// Client. A command palette on cmdk: the combobox / listbox roles, the active option (aria-activedescendant), the\n// arrows, Home / End, Enter, and the filtering (turn it off with `shouldFilter={false}` when the server searches).\n// `CommandDialog` puts it in the platform's Dialog. Words arrive as props.\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { DialogContent, type DialogContentProps } from \"../dialog/dialog\";\n\nexport const command = tv({\n slots: {\n root: \"flex h-full w-full flex-col overflow-hidden bg-surface-1 text-fg\",\n inputWrap: \"flex items-center gap-3 border-b border-border-default px-4\",\n icon: \"h-5 w-5 shrink-0 text-fg-secondary\",\n input:\n \"h-13 w-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted disabled:cursor-not-allowed disabled:opacity-50 sm:text-base\",\n list: \"max-h-[min(60dvh,26rem)] scroll-py-2 overflow-y-auto overscroll-contain p-2 [&:not(:has([cmdk-item]))]:p-0\",\n empty: \"px-3 py-8 text-center text-sm text-fg-secondary\",\n loading: \"px-3 py-6 text-center text-sm text-fg-secondary\",\n group:\n \"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pb-1.5 [&_[cmdk-group-heading]]:pt-3 [&_[cmdk-group-heading]]:text-xs \" +\n \"[&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-fg-secondary\",\n item:\n \"relative flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2.5 text-sm text-fg outline-hidden transition-colors \" +\n \"before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-transparent \" +\n \"data-[selected=true]:bg-surface-2 data-[selected=true]:before:bg-accent data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-40\",\n separator: \"-mx-2 my-1 h-px bg-border-subtle\",\n shortcut: \"ml-auto text-xs tracking-widest text-fg-secondary\",\n },\n});\nconst s = command();\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </svg>\n );\n}\n\nexport type CommandRootProps = React.ComponentProps<typeof CommandPrimitive> & {\n /** The accessible name of the palette — passed translated (\"Search\", \"Commands\"). */\n label: string;\n};\n\n/** The palette: `value` / `onValueChange` (the active item), `shouldFilter`, `filter`, `loop`. */\nexport function CommandRoot({ className, ...props }: CommandRootProps) {\n return <CommandPrimitive className={s.root({ className })} {...props} />;\n}\n\nexport type CommandInputProps = Omit<React.ComponentProps<typeof CommandPrimitive.Input>, \"placeholder\"> & {\n /** What to type — passed translated. The input is named by the palette's `label`. */\n placeholder: string;\n /** After the input, inside the bar: a spinner, a clear button. */\n trailing?: React.ReactNode;\n};\n\n/** The search field (`value` / `onValueChange` for the query), with a magnifier. */\nexport function CommandInput({ className, placeholder, trailing, ...props }: CommandInputProps) {\n return (\n <div className={s.inputWrap()} cmdk-input-wrapper=\"\">\n <SearchIcon className={s.icon()} />\n <CommandPrimitive.Input placeholder={placeholder} className={s.input({ className })} {...props} />\n {trailing}\n </div>\n );\n}\n\n// Set inside `Command.List`: a listbox may only hold options and groups (axe `aria-required-children`), so the empty\n// message must live beside it, not in it.\nconst InsideList = React.createContext(false);\n\nexport type CommandListProps = React.ComponentProps<typeof CommandPrimitive.List> & {\n /** The accessible name of the list of results — passed translated (\"Suggestions\", \"Results\"). */\n label: string;\n /**\n * Shown when nothing matches — passed translated. Rendered after the listbox, never inside it: an empty listbox is\n * valid, a listbox holding text is not.\n */\n emptyLabel?: React.ReactNode;\n};\n\nexport function CommandList({ className, emptyLabel, children, ...props }: CommandListProps) {\n return (\n <>\n <CommandPrimitive.List className={s.list({ className })} {...props}>\n <InsideList.Provider value>{children}</InsideList.Provider>\n </CommandPrimitive.List>\n {emptyLabel === undefined ? null : <CommandEmpty emptyLabel={emptyLabel} />}\n </>\n );\n}\n\nexport type CommandEmptyProps = Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, \"children\"> & {\n /** Shown when nothing matches — passed translated. */\n emptyLabel: React.ReactNode;\n};\n\n/**\n * Shown by cmdk only when no item matches. Place it beside `Command.List` (or pass `emptyLabel` to the list), never\n * inside it: inside, it is rendered as before but warns in development — the listbox then holds text, which axe\n * refuses (`aria-required-children`).\n */\nexport function CommandEmpty({ className, emptyLabel, ...props }: CommandEmptyProps) {\n const inside = React.useContext(InsideList);\n React.useEffect(() => {\n if (inside && typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\") {\n console.warn(\"@krizaka/ui/command: <Command.Empty> inside <Command.List> breaks the listbox (axe aria-required-children). Pass `emptyLabel` to <Command.List> instead.\");\n }\n }, [inside]);\n return (\n <CommandPrimitive.Empty className={s.empty({ className })} {...props}>\n {emptyLabel}\n </CommandPrimitive.Empty>\n );\n}\n\n/** While results load (`label` is announced). */\nexport function CommandLoading({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Loading>) {\n return <CommandPrimitive.Loading className={s.loading({ className })} {...props} />;\n}\n\n/** A group of items under a `heading`. */\nexport function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return <CommandPrimitive.Group className={s.group({ className })} {...props} />;\n}\n\n/** An option: `onSelect` on Enter or click, `value` and `keywords` for the filter, `disabled`. */\nexport function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return <CommandPrimitive.Item className={s.item({ className })} {...props} />;\n}\n\n/** A line between groups. Decorative (`role=\"none\"`): cmdk's own separator is a role a listbox may not hold (axe). */\nexport function CommandSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div role=\"none\" className={s.separator({ className })} {...props} />;\n}\n\n/** A keyboard hint at the end of an item. */\nexport function CommandShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n return <span className={s.shortcut({ className })} {...props} />;\n}\n\n/** `Command.Root/Input/List/Empty/Loading/Group/Item/Separator/Shortcut`. */\nexport const Command = {\n Root: CommandRoot,\n Input: CommandInput,\n List: CommandList,\n Empty: CommandEmpty,\n Loading: CommandLoading,\n Group: CommandGroup,\n Item: CommandItem,\n Separator: CommandSeparator,\n Shortcut: CommandShortcut,\n};\n\nexport type CommandDialogProps = Omit<CommandRootProps, \"title\"> & {\n /** Open or closed (controlled), with `onOpenChange`. */\n open?: boolean;\n /** Open at first, uncontrolled. */\n defaultOpen?: boolean;\n /** Called when it opens or closes (Escape, a click outside, a shortcut of the product). */\n onOpenChange?: (open: boolean) => void;\n /** Under the palette, inside the dialog: shortcuts, a \"see all results\" link. */\n footer?: React.ReactNode;\n /** Passed to `Dialog.Content`: `size`, `container`, `className` of the dialog. */\n contentProps?: Omit<Extract<DialogContentProps, { hideClose: true }>, \"hideClose\" | \"children\" | \"placement\">;\n};\n\n/**\n * The palette in a dialog (Radix: focus trap, Escape, focus return). The dialog is named by `label`; it has no close\n * button — Escape and a click outside close it — and the input takes the focus when it opens.\n */\nexport function CommandDialog({ open, defaultOpen, onOpenChange, footer, contentProps, label, className, children, ...props }: CommandDialogProps) {\n const { className: contentClassName, ...content } = contentProps ?? {};\n return (\n <DialogPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <DialogContent\n hideClose\n size=\"lg\"\n aria-describedby={undefined}\n className={cn(\"top-[12dvh] translate-y-0 sm:top-[14dvh]\", contentClassName)}\n {...content}\n >\n <DialogPrimitive.Title className=\"sr-only\">{label}</DialogPrimitive.Title>\n <CommandRoot label={label} className={className} {...props}>\n {children}\n </CommandRoot>\n {footer}\n </DialogContent>\n </DialogPrimitive.Root>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/component-page/component-page.tsx"],"sourcesContent":["// Server-safe. The page of one component of a design system (what krizaka.com/docs/ui draws from the registry): its\n// name, summary, status and platforms; the live preview with its code; installation; when to use it and when not; its\n// examples; its props; its accessibility — the facts in a side column that goes under the content on a phone.\nimport { CodeBlock } from \"@krizaka/ui/code-block\";\nimport { DetailLayout } from \"@krizaka/ui/detail-layout\";\nimport { type Fact, Facts, Section } from \"@krizaka/ui/page\";\nimport type * as React from \"react\";\n\nexport interface ComponentPageSection {\n /** The section's anchor. */\n id: string;\n /** Its title (`When to use`, `Props`). */\n title: React.ReactNode;\n /** Its content (lists, a props table, examples). */\n children: React.ReactNode;\n}\n\nexport type ComponentPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back to the catalogue (your router's link). */\n back?: React.ReactNode;\n /** The category (`Blocks`, `Forms`). */\n eyebrow?: React.ReactNode;\n /** The component's name: the `h1`. */\n title: React.ReactNode;\n /** Its summary, in one sentence. */\n summary: React.ReactNode;\n /** Its status and platforms. */\n facts?: readonly Fact[];\n /** The live preview of its first example (a framed stage with its code). */\n preview: React.ReactNode;\n /** The line to install or import it, and the copy words. */\n install?: { code: string; language?: string; copyLabel: string; copiedLabel: string; file?: React.ReactNode };\n /** The sections, in reading order: when to use / not, examples, props, accessibility. */\n sections: readonly ComponentPageSection[];\n /** The side column: related components, source, the version. */\n aside?: React.ReactNode;\n};\n\n/** A component's page: name, summary, facts, live preview, install, then its sections; facts and related aside. */\nexport function ComponentPage({ back, eyebrow, title, summary, facts, preview, install, sections, aside, ...props }: ComponentPageProps) {\n return (\n <DetailLayout back={back} eyebrow={eyebrow} title={title} meta={<span>{summary}</span>} aside={aside} {...props}>\n {facts && facts.length > 0 && <Facts items={facts} />}\n <div className=\"kz-tpl-stage\">{preview}</div>\n {install && <CodeBlock code={install.code} language={install.language ?? \"bash\"} file={install.file} copyLabel={install.copyLabel} copiedLabel={install.copiedLabel} />}\n <div className=\"kz-tpl-flush\">\n {sections.map((s) => (\n <Section key={s.id} id={s.id} title={s.title} headingSize=\"sm\" spacing=\"sm\" size=\"full\" divider>\n {s.children}\n </Section>\n ))}\n </div>\n </DetailLayout>\n );\n}\n"],"mappings":";AAGA,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAoB,OAAO,eAAe;AAoCtC,SAAgE,KAAhE;AAFG,SAAS,cAAc,EAAE,MAAM,SAAS,OAAO,SAAS,OAAO,SAAS,SAAS,UAAU,OAAO,GAAG,MAAM,GAAuB;AACvI,SACE,qBAAC,gBAAa,MAAY,SAAkB,OAAc,MAAM,oBAAC,UAAM,mBAAQ,GAAS,OAAe,GAAG,OACvG;AAAA,aAAS,MAAM,SAAS,KAAK,oBAAC,SAAM,OAAO,OAAO;AAAA,IACnD,oBAAC,SAAI,WAAU,gBAAgB,mBAAQ;AAAA,IACtC,WAAW,oBAAC,aAAU,MAAM,QAAQ,MAAM,UAAU,QAAQ,YAAY,QAAQ,MAAM,QAAQ,MAAM,WAAW,QAAQ,WAAW,aAAa,QAAQ,aAAa;AAAA,IACrK,oBAAC,SAAI,WAAU,gBACZ,mBAAS,IAAI,CAAC,MACb,oBAAC,WAAmB,IAAI,EAAE,IAAI,OAAO,EAAE,OAAO,aAAY,MAAK,SAAQ,MAAK,MAAK,QAAO,SAAO,MAC5F,YAAE,YADS,EAAE,EAEhB,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/component-page/component-page.tsx"],"sourcesContent":["// Server-safe. The page of one component of a design system (what ui.krizaka.com draws from the registry): its\n// name, summary, status and platforms; the live preview with its code; installation; when to use it and when not; its\n// examples; its props; its accessibility — the facts in a side column that goes under the content on a phone.\nimport { CodeBlock } from \"@krizaka/ui/code-block\";\nimport { DetailLayout } from \"@krizaka/ui/detail-layout\";\nimport { type Fact, Facts, Section } from \"@krizaka/ui/page\";\nimport type * as React from \"react\";\n\nexport interface ComponentPageSection {\n /** The section's anchor. */\n id: string;\n /** Its title (`When to use`, `Props`). */\n title: React.ReactNode;\n /** Its content (lists, a props table, examples). */\n children: React.ReactNode;\n}\n\nexport type ComponentPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back to the catalogue (your router's link). */\n back?: React.ReactNode;\n /** The category (`Blocks`, `Forms`). */\n eyebrow?: React.ReactNode;\n /** The component's name: the `h1`. */\n title: React.ReactNode;\n /** Its summary, in one sentence. */\n summary: React.ReactNode;\n /** Its status and platforms. */\n facts?: readonly Fact[];\n /** The live preview of its first example (a framed stage with its code). */\n preview: React.ReactNode;\n /** The line to install or import it, and the copy words. */\n install?: { code: string; language?: string; copyLabel: string; copiedLabel: string; file?: React.ReactNode };\n /** The sections, in reading order: when to use / not, examples, props, accessibility. */\n sections: readonly ComponentPageSection[];\n /** The side column: related components, source, the version. */\n aside?: React.ReactNode;\n};\n\n/** A component's page: name, summary, facts, live preview, install, then its sections; facts and related aside. */\nexport function ComponentPage({ back, eyebrow, title, summary, facts, preview, install, sections, aside, ...props }: ComponentPageProps) {\n return (\n <DetailLayout back={back} eyebrow={eyebrow} title={title} meta={<span>{summary}</span>} aside={aside} {...props}>\n {facts && facts.length > 0 && <Facts items={facts} />}\n <div className=\"kz-tpl-stage\">{preview}</div>\n {install && <CodeBlock code={install.code} language={install.language ?? \"bash\"} file={install.file} copyLabel={install.copyLabel} copiedLabel={install.copiedLabel} />}\n <div className=\"kz-tpl-flush\">\n {sections.map((s) => (\n <Section key={s.id} id={s.id} title={s.title} headingSize=\"sm\" spacing=\"sm\" size=\"full\" divider>\n {s.children}\n </Section>\n ))}\n </div>\n </DetailLayout>\n );\n}\n"],"mappings":";AAGA,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAoB,OAAO,eAAe;AAoCtC,SAAgE,KAAhE;AAFG,SAAS,cAAc,EAAE,MAAM,SAAS,OAAO,SAAS,OAAO,SAAS,SAAS,UAAU,OAAO,GAAG,MAAM,GAAuB;AACvI,SACE,qBAAC,gBAAa,MAAY,SAAkB,OAAc,MAAM,oBAAC,UAAM,mBAAQ,GAAS,OAAe,GAAG,OACvG;AAAA,aAAS,MAAM,SAAS,KAAK,oBAAC,SAAM,OAAO,OAAO;AAAA,IACnD,oBAAC,SAAI,WAAU,gBAAgB,mBAAQ;AAAA,IACtC,WAAW,oBAAC,aAAU,MAAM,QAAQ,MAAM,UAAU,QAAQ,YAAY,QAAQ,MAAM,QAAQ,MAAM,WAAW,QAAQ,WAAW,aAAa,QAAQ,aAAa;AAAA,IACrK,oBAAC,SAAI,WAAU,gBACZ,mBAAS,IAAI,CAAC,MACb,oBAAC,WAAmB,IAAI,EAAE,IAAI,OAAO,EAAE,OAAO,aAAY,MAAK,SAAQ,MAAK,MAAK,QAAO,SAAO,MAC5F,YAAE,YADS,EAAE,EAEhB,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { B as ButtonProps } from './button-BMAO7dKF.js';
2
+ import { B as ButtonProps } from './button-BmCrLCq7.js';
3
3
  import 'tailwind-variants';
4
4
 
5
5
  declare const confirmArmed = "border border-danger bg-danger/20 text-fg hover:border-danger hover:bg-danger/30";
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  Button
4
- } from "./chunk-RUPNPMP3.js";
4
+ } from "./chunk-OWC2LZD2.js";
5
+ import "./chunk-D3T54RSL.js";
5
6
  import "./chunk-WEVYKZIF.js";
6
7
  import {
7
8
  cn
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/confirm-button/confirm-button.tsx"],"sourcesContent":["// Client (a state). A destructive action confirmed by a second press, never `window.confirm`: the first press arms it\n// and says what will happen (`confirmLabel`, announced politely), the second runs `onConfirm`. It disarms by itself\n// after `timeoutMs`, on Escape, and when the focus leaves. The danger is the border and the tint; the words stay a\n// text role (contrast AA in both themes).\nimport { VisuallyHidden } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button, type ButtonProps } from \"../button/button\";\nimport { cn } from \"../cn\";\n\nexport const confirmArmed = \"border border-danger bg-danger/20 text-fg hover:border-danger hover:bg-danger/30\";\n\nexport type ConfirmButtonProps = Omit<ButtonProps, \"onClick\" | \"asChild\"> & {\n /** What the second press does, in words — shown and announced once armed (\"Delete for good?\"). Passed translated. */\n confirmLabel: string;\n /** The accessible name while idle, for an icon-only button (the confirm label names it once armed). */\n label?: string;\n /** Runs on the second press. */\n onConfirm: () => void;\n /** Disarms after this many milliseconds (4000 by default). */\n timeoutMs?: number;\n /** What it shows once armed (default: its children, then `confirmLabel`). */\n armedContent?: React.ReactNode;\n /** Notified when it arms and disarms. */\n onArmedChange?: (armed: boolean) => void;\n};\n\n/** A two-step button: press to arm, press again within `timeoutMs` to confirm. State: `data-armed`. */\nexport function ConfirmButton({\n confirmLabel,\n label,\n onConfirm,\n timeoutMs = 4000,\n onArmedChange,\n armedContent,\n variant = \"ghost\",\n className,\n children,\n onBlur,\n onKeyDown,\n ...props\n}: ConfirmButtonProps) {\n const [armed, setArmedState] = React.useState(false);\n const armedRef = React.useRef(false);\n const onArmedChangeRef = React.useRef(onArmedChange);\n React.useEffect(() => {\n onArmedChangeRef.current = onArmedChange;\n }, [onArmedChange]);\n const setArmed = React.useCallback((next: boolean) => {\n if (armedRef.current === next) return;\n armedRef.current = next;\n setArmedState(next);\n onArmedChangeRef.current?.(next);\n }, []);\n React.useEffect(() => {\n if (!armed) return;\n const timer = window.setTimeout(() => setArmed(false), timeoutMs);\n return () => window.clearTimeout(timer);\n }, [armed, timeoutMs, setArmed]);\n const name = armed ? confirmLabel : label;\n return (\n <>\n <Button\n variant={variant}\n aria-label={name}\n title={name}\n data-armed={armed ? \"\" : undefined}\n className={cn(armed && confirmArmed, className)}\n onClick={() => {\n if (!armed) return setArmed(true);\n setArmed(false);\n onConfirm();\n }}\n onBlur={(event) => {\n onBlur?.(event);\n setArmed(false);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (armed && event.key === \"Escape\") {\n event.stopPropagation();\n setArmed(false);\n }\n }}\n {...props}\n >\n {armed\n ? (armedContent ?? (\n <>\n {children}\n <span>{confirmLabel}</span>\n </>\n ))\n : children}\n </Button>\n <VisuallyHidden.Root aria-live=\"polite\">{armed ? confirmLabel : \"\"}</VisuallyHidden.Root>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAIA,SAAS,sBAAsB;AAC/B,YAAY,WAAW;AAmFT,mBAEE,KAFF;AA9EP,IAAM,eAAe;AAkBrB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAuB;AACrB,QAAM,CAAC,OAAO,aAAa,IAAU,eAAS,KAAK;AACnD,QAAM,WAAiB,aAAO,KAAK;AACnC,QAAM,mBAAyB,aAAO,aAAa;AACnD,EAAM,gBAAU,MAAM;AACpB,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,WAAiB,kBAAY,CAAC,SAAkB;AACpD,QAAI,SAAS,YAAY,KAAM;AAC/B,aAAS,UAAU;AACnB,kBAAc,IAAI;AAClB,qBAAiB,UAAU,IAAI;AAAA,EACjC,GAAG,CAAC,CAAC;AACL,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,OAAO,WAAW,MAAM,SAAS,KAAK,GAAG,SAAS;AAChE,WAAO,MAAM,OAAO,aAAa,KAAK;AAAA,EACxC,GAAG,CAAC,OAAO,WAAW,QAAQ,CAAC;AAC/B,QAAM,OAAO,QAAQ,eAAe;AACpC,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,cAAY;AAAA,QACZ,OAAO;AAAA,QACP,cAAY,QAAQ,KAAK;AAAA,QACzB,WAAW,GAAG,SAAS,cAAc,SAAS;AAAA,QAC9C,SAAS,MAAM;AACb,cAAI,CAAC,MAAO,QAAO,SAAS,IAAI;AAChC,mBAAS,KAAK;AACd,oBAAU;AAAA,QACZ;AAAA,QACA,QAAQ,CAAC,UAAU;AACjB,mBAAS,KAAK;AACd,mBAAS,KAAK;AAAA,QAChB;AAAA,QACA,WAAW,CAAC,UAAU;AACpB,sBAAY,KAAK;AACjB,cAAI,SAAS,MAAM,QAAQ,UAAU;AACnC,kBAAM,gBAAgB;AACtB,qBAAS,KAAK;AAAA,UAChB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH,kBACI,gBACC,iCACG;AAAA;AAAA,UACD,oBAAC,UAAM,wBAAa;AAAA,WACtB,IAEF;AAAA;AAAA,IACN;AAAA,IACA,oBAAC,eAAe,MAAf,EAAoB,aAAU,UAAU,kBAAQ,eAAe,IAAG;AAAA,KACrE;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/confirm-button/confirm-button.tsx"],"sourcesContent":["// Client (a state). A destructive action confirmed by a second press, never `window.confirm`: the first press arms it\n// and says what will happen (`confirmLabel`, announced politely), the second runs `onConfirm`. It disarms by itself\n// after `timeoutMs`, on Escape, and when the focus leaves. The danger is the border and the tint; the words stay a\n// text role (contrast AA in both themes).\nimport { VisuallyHidden } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button, type ButtonProps } from \"../button/button\";\nimport { cn } from \"../cn\";\n\nexport const confirmArmed = \"border border-danger bg-danger/20 text-fg hover:border-danger hover:bg-danger/30\";\n\nexport type ConfirmButtonProps = Omit<ButtonProps, \"onClick\" | \"asChild\"> & {\n /** What the second press does, in words — shown and announced once armed (\"Delete for good?\"). Passed translated. */\n confirmLabel: string;\n /** The accessible name while idle, for an icon-only button (the confirm label names it once armed). */\n label?: string;\n /** Runs on the second press. */\n onConfirm: () => void;\n /** Disarms after this many milliseconds (4000 by default). */\n timeoutMs?: number;\n /** What it shows once armed (default: its children, then `confirmLabel`). */\n armedContent?: React.ReactNode;\n /** Notified when it arms and disarms. */\n onArmedChange?: (armed: boolean) => void;\n};\n\n/** A two-step button: press to arm, press again within `timeoutMs` to confirm. State: `data-armed`. */\nexport function ConfirmButton({\n confirmLabel,\n label,\n onConfirm,\n timeoutMs = 4000,\n onArmedChange,\n armedContent,\n variant = \"ghost\",\n className,\n children,\n onBlur,\n onKeyDown,\n ...props\n}: ConfirmButtonProps) {\n const [armed, setArmedState] = React.useState(false);\n const armedRef = React.useRef(false);\n const onArmedChangeRef = React.useRef(onArmedChange);\n React.useEffect(() => {\n onArmedChangeRef.current = onArmedChange;\n }, [onArmedChange]);\n const setArmed = React.useCallback((next: boolean) => {\n if (armedRef.current === next) return;\n armedRef.current = next;\n setArmedState(next);\n onArmedChangeRef.current?.(next);\n }, []);\n React.useEffect(() => {\n if (!armed) return;\n const timer = window.setTimeout(() => setArmed(false), timeoutMs);\n return () => window.clearTimeout(timer);\n }, [armed, timeoutMs, setArmed]);\n const name = armed ? confirmLabel : label;\n return (\n <>\n <Button\n variant={variant}\n aria-label={name}\n title={name}\n data-armed={armed ? \"\" : undefined}\n className={cn(armed && confirmArmed, className)}\n onClick={() => {\n if (!armed) return setArmed(true);\n setArmed(false);\n onConfirm();\n }}\n onBlur={(event) => {\n onBlur?.(event);\n setArmed(false);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (armed && event.key === \"Escape\") {\n event.stopPropagation();\n setArmed(false);\n }\n }}\n {...props}\n >\n {armed\n ? (armedContent ?? (\n <>\n {children}\n <span>{confirmLabel}</span>\n </>\n ))\n : children}\n </Button>\n <VisuallyHidden.Root aria-live=\"polite\">{armed ? confirmLabel : \"\"}</VisuallyHidden.Root>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;AAIA,SAAS,sBAAsB;AAC/B,YAAY,WAAW;AAmFT,mBAEE,KAFF;AA9EP,IAAM,eAAe;AAkBrB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAuB;AACrB,QAAM,CAAC,OAAO,aAAa,IAAU,eAAS,KAAK;AACnD,QAAM,WAAiB,aAAO,KAAK;AACnC,QAAM,mBAAyB,aAAO,aAAa;AACnD,EAAM,gBAAU,MAAM;AACpB,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,WAAiB,kBAAY,CAAC,SAAkB;AACpD,QAAI,SAAS,YAAY,KAAM;AAC/B,aAAS,UAAU;AACnB,kBAAc,IAAI;AAClB,qBAAiB,UAAU,IAAI;AAAA,EACjC,GAAG,CAAC,CAAC;AACL,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,OAAO,WAAW,MAAM,SAAS,KAAK,GAAG,SAAS;AAChE,WAAO,MAAM,OAAO,aAAa,KAAK;AAAA,EACxC,GAAG,CAAC,OAAO,WAAW,QAAQ,CAAC;AAC/B,QAAM,OAAO,QAAQ,eAAe;AACpC,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,cAAY;AAAA,QACZ,OAAO;AAAA,QACP,cAAY,QAAQ,KAAK;AAAA,QACzB,WAAW,GAAG,SAAS,cAAc,SAAS;AAAA,QAC9C,SAAS,MAAM;AACb,cAAI,CAAC,MAAO,QAAO,SAAS,IAAI;AAChC,mBAAS,KAAK;AACd,oBAAU;AAAA,QACZ;AAAA,QACA,QAAQ,CAAC,UAAU;AACjB,mBAAS,KAAK;AACd,mBAAS,KAAK;AAAA,QAChB;AAAA,QACA,WAAW,CAAC,UAAU;AACpB,sBAAY,KAAK;AACjB,cAAI,SAAS,MAAM,QAAQ,UAAU;AACnC,kBAAM,gBAAgB;AACtB,qBAAS,KAAK;AAAA,UAChB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH,kBACI,gBACC,iCACG;AAAA;AAAA,UACD,oBAAC,UAAM,wBAAa;AAAA,WACtB,IAEF;AAAA;AAAA,IACN;AAAA,IACA,oBAAC,eAAe,MAAf,EAAoB,aAAU,UAAU,kBAAQ,eAAe,IAAG;AAAA,KACrE;AAEJ;","names":[]}
@@ -35,9 +35,13 @@ function LoaderGlyph({ state = "loading", value, ...props }) {
35
35
  ] });
36
36
  }
37
37
 
38
- // src/button/button.tsx
39
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
40
- var buttonVariants = tv({
38
+ // src/recipes/define.ts
39
+ function defineRecipe(config) {
40
+ return config;
41
+ }
42
+
43
+ // src/button/recipe.ts
44
+ var buttonRecipe = defineRecipe({
41
45
  base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] [&[data-loading]]:opacity-100",
42
46
  variants: {
43
47
  variant: {
@@ -58,6 +62,10 @@ var buttonVariants = tv({
58
62
  },
59
63
  defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
60
64
  });
65
+
66
+ // src/button/button.tsx
67
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
68
+ var buttonVariants = tv(buttonRecipe);
61
69
  var STATUS_TEXT = { success: "text-fg-success", error: "text-fg-danger" };
62
70
  function Button({
63
71
  asChild,