@krizaka/ui 3.25.0 → 3.27.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 (180) hide show
  1. package/README.md +2 -1
  2. package/dist/chunk-3S4GHSPZ.js +109 -0
  3. package/dist/chunk-3S4GHSPZ.js.map +1 -0
  4. package/dist/{chunk-FTX66XZY.js → chunk-OUWPBSSL.js} +4 -4
  5. package/dist/{chunk-FTX66XZY.js.map → chunk-OUWPBSSL.js.map} +1 -1
  6. package/dist/{chunk-4DH2HW3D.js → chunk-TFJDIOFK.js} +2 -1
  7. package/dist/document-viewer.js +19 -3
  8. package/dist/document-viewer.js.map +1 -1
  9. package/dist/image-cropper.js +8 -4
  10. package/dist/image-cropper.js.map +1 -1
  11. package/dist/index.d.ts +3 -8
  12. package/dist/index.js +44 -48
  13. package/dist/index.js.map +1 -1
  14. package/dist/language-switch/server.d.ts +17 -0
  15. package/dist/language-switch/server.js +26 -0
  16. package/dist/language-switch/server.js.map +1 -0
  17. package/dist/language-switch.d.ts +120 -0
  18. package/dist/language-switch.js +34 -0
  19. package/dist/language-switch.js.map +1 -0
  20. package/dist/nav-bar.d.ts +52 -4
  21. package/dist/nav-bar.js +77 -14
  22. package/dist/nav-bar.js.map +1 -1
  23. package/dist/site-footer.js +2 -2
  24. package/dist/sites.js +2 -2
  25. package/dist/sites.js.map +1 -1
  26. package/package.json +32 -8
  27. package/registry/account-menu.json +1 -1
  28. package/registry/achievement.json +1 -1
  29. package/registry/action-bar.json +1 -1
  30. package/registry/activity-feed.json +1 -1
  31. package/registry/alert.json +1 -1
  32. package/registry/app-header.json +1 -1
  33. package/registry/app-shell.json +1 -1
  34. package/registry/argument-card.json +1 -1
  35. package/registry/audio-player.json +1 -1
  36. package/registry/auth-layout.json +1 -1
  37. package/registry/avatar.json +1 -1
  38. package/registry/badge.json +1 -1
  39. package/registry/button.json +1 -1
  40. package/registry/captcha.json +1 -1
  41. package/registry/card-grid.json +1 -1
  42. package/registry/card.json +1 -1
  43. package/registry/catalogue-page.json +1 -1
  44. package/registry/changelog-page.json +1 -1
  45. package/registry/chat.json +1 -1
  46. package/registry/checkbox.json +1 -1
  47. package/registry/chip-link.json +1 -1
  48. package/registry/chip.json +1 -1
  49. package/registry/choice-grid.json +1 -1
  50. package/registry/code-block.json +1 -1
  51. package/registry/combobox.json +1 -1
  52. package/registry/command.json +1 -1
  53. package/registry/comparison-table.json +1 -1
  54. package/registry/component-page.json +1 -1
  55. package/registry/confirm-button.json +1 -1
  56. package/registry/contact-page.json +1 -1
  57. package/registry/continue-prompt.json +1 -1
  58. package/registry/countdown.json +1 -1
  59. package/registry/cover-hero.json +1 -1
  60. package/registry/cta-panel.json +1 -1
  61. package/registry/dashboard-layout.json +1 -1
  62. package/registry/data-table.json +1 -1
  63. package/registry/date-picker.json +1 -1
  64. package/registry/decision-list.json +1 -1
  65. package/registry/description-list.json +1 -1
  66. package/registry/detail-layout.json +1 -1
  67. package/registry/dialog.json +1 -1
  68. package/registry/docs-article-page.json +1 -1
  69. package/registry/docs-hub-page.json +1 -1
  70. package/registry/docs-layout.json +1 -1
  71. package/registry/docs-nav.json +1 -1
  72. package/registry/document-viewer.json +2 -2
  73. package/registry/dropdown-menu.json +1 -1
  74. package/registry/empty-state.json +1 -1
  75. package/registry/error-page.json +1 -1
  76. package/registry/examples/language-switch/inline.d.ts +4 -0
  77. package/registry/examples/language-switch/inline.js +11 -0
  78. package/registry/examples/language-switch/inline.tsx +6 -0
  79. package/registry/examples/language-switch/menu.d.ts +4 -0
  80. package/registry/examples/language-switch/menu.js +11 -0
  81. package/registry/examples/language-switch/menu.tsx +6 -0
  82. package/registry/examples/nav-bar/family-product.js +18 -10
  83. package/registry/examples/nav-bar/family-product.tsx +28 -27
  84. package/registry/field.json +1 -1
  85. package/registry/file-upload.json +1 -1
  86. package/registry/filter-bar.json +1 -1
  87. package/registry/force-update-screen.json +1 -1
  88. package/registry/form.json +1 -1
  89. package/registry/gallery-page.json +1 -1
  90. package/registry/genui.json +1 -1
  91. package/registry/glow-card.json +1 -1
  92. package/registry/goal-gauge.json +1 -1
  93. package/registry/how-it-works-page.json +1 -1
  94. package/registry/image-cropper.json +2 -2
  95. package/registry/index.json +37 -5
  96. package/registry/iso.json +1 -1
  97. package/registry/kanban.json +1 -1
  98. package/registry/kbd.json +1 -1
  99. package/registry/landing-page.json +1 -1
  100. package/registry/landscape.json +1 -1
  101. package/registry/language-switch.json +250 -0
  102. package/registry/legal-page.json +1 -1
  103. package/registry/link-card.json +1 -1
  104. package/registry/list.json +1 -1
  105. package/registry/loader.json +1 -1
  106. package/registry/longform-page.json +1 -1
  107. package/registry/maintenance-screen.json +1 -1
  108. package/registry/map.json +2 -2
  109. package/registry/markdown.json +1 -1
  110. package/registry/marketing-layout.json +1 -1
  111. package/registry/marquee.json +1 -1
  112. package/registry/mascot-quote.json +1 -1
  113. package/registry/mascot-state.json +1 -1
  114. package/registry/mascots.json +1 -1
  115. package/registry/match-dialog.json +1 -1
  116. package/registry/media-capture.json +1 -1
  117. package/registry/media-gallery.json +1 -1
  118. package/registry/media-grid.json +1 -1
  119. package/registry/meta-row.json +1 -1
  120. package/registry/meter.json +1 -1
  121. package/registry/nav-bar.json +155 -10
  122. package/registry/number-ticker.json +1 -1
  123. package/registry/opening-hours.json +1 -1
  124. package/registry/page-header.json +1 -1
  125. package/registry/page-hero.json +1 -1
  126. package/registry/page.json +1 -1
  127. package/registry/pagination.json +1 -1
  128. package/registry/photo-grid.json +1 -1
  129. package/registry/pointer-light.json +1 -1
  130. package/registry/popover.json +1 -1
  131. package/registry/pricing-page.json +1 -1
  132. package/registry/product-page.json +1 -1
  133. package/registry/profile-card.json +1 -1
  134. package/registry/progress.json +1 -1
  135. package/registry/promise-card.json +1 -1
  136. package/registry/radio-group.json +1 -1
  137. package/registry/rail-nav.json +2 -2
  138. package/registry/recipes.json +1 -1
  139. package/registry/scroll-stage.json +1 -1
  140. package/registry/search-field.json +1 -1
  141. package/registry/section-backdrop.json +1 -1
  142. package/registry/separator.json +1 -1
  143. package/registry/service-card.json +1 -1
  144. package/registry/settings-layout.json +1 -1
  145. package/registry/showcase.json +1 -1
  146. package/registry/site-footer.json +2 -2
  147. package/registry/sites.json +2 -2
  148. package/registry/skeleton.json +1 -1
  149. package/registry/skip-link.json +1 -1
  150. package/registry/slider.json +1 -1
  151. package/registry/slot-picker.json +1 -1
  152. package/registry/slot.json +1 -1
  153. package/registry/spinner.json +1 -1
  154. package/registry/split-view.json +1 -1
  155. package/registry/stage-banner.json +1 -1
  156. package/registry/stat.json +1 -1
  157. package/registry/status-page.json +1 -1
  158. package/registry/step-progress.json +1 -1
  159. package/registry/step-showcase.json +1 -1
  160. package/registry/stepper.json +1 -1
  161. package/registry/sticky-action.json +1 -1
  162. package/registry/swipe-deck.json +1 -1
  163. package/registry/switch.json +1 -1
  164. package/registry/tabs.json +1 -1
  165. package/registry/tag-input.json +1 -1
  166. package/registry/tag-selector.json +1 -1
  167. package/registry/terminal-replay.json +1 -1
  168. package/registry/theme.json +1 -1
  169. package/registry/toast.json +1 -1
  170. package/registry/toc.json +1 -1
  171. package/registry/tooltip.json +1 -1
  172. package/registry/tree-view.json +1 -1
  173. package/registry/update-prompt.json +1 -1
  174. package/registry/verified-badge.json +1 -1
  175. package/registry/vertical-video.json +1 -1
  176. package/registry/video-player.json +1 -1
  177. package/registry/video-trimmer.json +1 -1
  178. package/registry/virtual.json +1 -1
  179. package/registry/waveform.json +1 -1
  180. /package/dist/{chunk-4DH2HW3D.js.map → chunk-TFJDIOFK.js.map} +0 -0
package/dist/index.js CHANGED
@@ -18,63 +18,59 @@ import {
18
18
  YomizakaLogo,
19
19
  YororisLogo,
20
20
  a11y,
21
- neutral
22
- } from "./chunk-4DH2HW3D.js";
21
+ neutral,
22
+ useIds
23
+ } from "./chunk-TFJDIOFK.js";
23
24
 
24
25
  // src/marks/wu-sama-geometry.ts
25
- var round = (n) => Math.round(n * 10) / 10;
26
- var center = 200;
27
- var radius = 150;
28
- var u = radius * Math.sqrt(3) / 2;
29
- var gap = 10;
30
- var hexagon = [
31
- [center, center - radius],
32
- [round(center + u), center - radius / 2],
33
- [round(center + u), center + radius / 2],
34
- [center, center + radius],
35
- [round(center - u), center + radius / 2],
36
- [round(center - u), center - radius / 2]
37
- ];
38
- var [T, UR, LR, B, LL, UL] = hexagon;
39
- var onEdge = (a, b, x) => [x, round(a[1] + (x - a[0]) / (b[0] - a[0]) * (b[1] - a[1]))];
40
- var pt = ([x, y]) => `${x},${y}`;
41
- var left = [onEdge(T, UL, center - gap), UL, LL, onEdge(B, LL, center - gap)];
42
- var right = [onEdge(T, UR, center + gap), UR, LR, onEdge(B, LR, center + gap)];
43
- var wPoints = [
44
- [round(center - 0.63 * u), round(center - 0.4 * radius)],
45
- [round(center - 0.37 * u), round(center + 0.55 * radius)],
46
- [center, round(center - 0.03 * radius)],
47
- [round(center + 0.37 * u), round(center + 0.55 * radius)],
48
- [round(center + 0.63 * u), round(center - 0.4 * radius)]
49
- ];
50
- var peak = wPoints[2];
26
+ import { marks } from "@krizaka/tokens/native";
51
27
  var WU_SAMA = {
52
28
  viewBox: "0 0 400 400",
53
- croppedViewBox: "34 34 332 332",
54
- center,
55
- radius,
56
- gap,
57
- hexagon,
58
- /** The two halves of the hexagon (open at the top and bottom vertices), stroked in ink. */
59
- shell: { left: `M${left.map(pt).join(" L")}`, right: `M${right.map(pt).join(" L")}`, stroke: 22 },
60
- /** The W, stroked in gold. */
61
- w: `M${wPoints.map(pt).join(" L")}`,
62
- wStroke: 26,
63
- /** The node: the family's lit node, a small diamond at the W's middle summit, in ink. */
64
- node: `M${center},${round(peak[1] - 24)} L${center + 18},${peak[1]} L${center},${round(peak[1] + 24)} L${center - 18},${peak[1]}Z`,
65
- /** One mid-tone amber, hsl(40 94% 37%): 3.3:1 on white and 5.8:1 on the dark surface. */
66
- gold: "hsl(40 94% 37%)"
29
+ croppedViewBox: "86 82 228 228",
30
+ offset: 20,
31
+ /** The shield: the Krizaka pointy-top hexagon (r 92 around 180,180), open at its upper-right edge. */
32
+ shield: "M259.7,134 L259.7,226 L180,272 L100.3,226 L100.3,134 L180,88 L212,106.5",
33
+ stroke: 22,
34
+ ink: { x1: 70, y1: 290, x2: 290, y2: 70 },
35
+ blue: { x1: 180, y1: 180, x2: 300, y2: 60, stops: marks.krizaka },
36
+ /** The vertex where the shield opens: a lit node in Krizaka blue. */
37
+ node: { cx: 259.7, cy: 134, r: 19, inner: 6 },
38
+ /** The W: five straight legs in Krizaka blue. */
39
+ w: "M132,142 L154,216 L180,166 L206,216 L228,142",
40
+ wStroke: 18,
41
+ highlight: "#dbeafe",
42
+ glow: { color: "#196df5", opacity: 0.16 },
43
+ orbit: { r: 160, dash: "8 8", width: 1.5 },
44
+ ring: { r: 134, width: 1 }
67
45
  };
68
46
 
69
47
  // src/marks/WuSamaMark.tsx
70
- import { jsx, jsxs } from "react/jsx-runtime";
48
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
71
49
  function WuSamaMark({ size = 32, title, className }) {
72
- const ink = neutral("--kz-text-primary", 92);
50
+ const id = useIds("wsm", ["ink", "blue", "glow"]);
73
51
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: size < 48 ? WU_SAMA.croppedViewBox : WU_SAMA.viewBox, fill: "none", xmlns: "http://www.w3.org/2000/svg", className, ...a11y(title), children: [
74
- /* @__PURE__ */ jsx("path", { d: WU_SAMA.shell.left, stroke: ink, strokeWidth: WU_SAMA.shell.stroke, strokeLinejoin: "miter", strokeLinecap: "butt" }),
75
- /* @__PURE__ */ jsx("path", { d: WU_SAMA.shell.right, stroke: ink, strokeWidth: WU_SAMA.shell.stroke, strokeLinejoin: "miter", strokeLinecap: "butt" }),
76
- /* @__PURE__ */ jsx("path", { d: WU_SAMA.w, stroke: WU_SAMA.gold, strokeWidth: WU_SAMA.wStroke, strokeLinejoin: "miter", strokeMiterlimit: 4, strokeLinecap: "butt" }),
77
- /* @__PURE__ */ jsx("path", { d: WU_SAMA.node, fill: ink })
52
+ /* @__PURE__ */ jsxs("defs", { children: [
53
+ /* @__PURE__ */ jsxs("linearGradient", { id: id.ink, gradientUnits: "userSpaceOnUse", x1: WU_SAMA.ink.x1, y1: WU_SAMA.ink.y1, x2: WU_SAMA.ink.x2, y2: WU_SAMA.ink.y2, children: [
54
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: neutral("--kz-text-secondary", 60) }),
55
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: neutral("--kz-text-primary", 92) })
56
+ ] }),
57
+ /* @__PURE__ */ jsx("linearGradient", { id: id.blue, gradientUnits: "userSpaceOnUse", x1: WU_SAMA.blue.x1, y1: WU_SAMA.blue.y1, x2: WU_SAMA.blue.x2, y2: WU_SAMA.blue.y2, children: WU_SAMA.blue.stops.map(([offset, color]) => /* @__PURE__ */ jsx("stop", { offset, stopColor: color }, offset)) }),
58
+ /* @__PURE__ */ jsxs("radialGradient", { id: id.glow, cx: "50%", cy: "50%", r: "50%", children: [
59
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: WU_SAMA.glow.color, stopOpacity: WU_SAMA.glow.opacity }),
60
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: WU_SAMA.glow.color, stopOpacity: "0" })
61
+ ] })
62
+ ] }),
63
+ size >= 48 ? /* @__PURE__ */ jsx("circle", { cx: "200", cy: "200", r: "190", fill: `url(#${id.glow})` }) : null,
64
+ size >= 48 ? /* @__PURE__ */ jsxs(Fragment, { children: [
65
+ /* @__PURE__ */ jsx("circle", { cx: "200", cy: "200", r: WU_SAMA.orbit.r, stroke: neutral("--kz-border-strong", 40), strokeWidth: WU_SAMA.orbit.width, strokeDasharray: WU_SAMA.orbit.dash, opacity: ".6" }),
66
+ /* @__PURE__ */ jsx("circle", { cx: "200", cy: "200", r: WU_SAMA.ring.r, stroke: neutral("--kz-border-default", 30), strokeWidth: WU_SAMA.ring.width, opacity: ".35" })
67
+ ] }) : null,
68
+ /* @__PURE__ */ jsxs("g", { transform: `translate(${WU_SAMA.offset} ${WU_SAMA.offset})`, children: [
69
+ /* @__PURE__ */ jsx("path", { d: WU_SAMA.shield, stroke: `url(#${id.ink})`, strokeWidth: WU_SAMA.stroke, strokeLinecap: "round", strokeLinejoin: "round" }),
70
+ /* @__PURE__ */ jsx("circle", { cx: WU_SAMA.node.cx, cy: WU_SAMA.node.cy, r: WU_SAMA.node.r, fill: `url(#${id.blue})` }),
71
+ /* @__PURE__ */ jsx("circle", { cx: WU_SAMA.node.cx, cy: WU_SAMA.node.cy, r: WU_SAMA.node.inner, fill: WU_SAMA.highlight }),
72
+ /* @__PURE__ */ jsx("path", { d: WU_SAMA.w, stroke: `url(#${id.blue})`, strokeWidth: WU_SAMA.wStroke, strokeLinecap: "round", strokeLinejoin: "round" })
73
+ ] })
78
74
  ] });
79
75
  }
80
76
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/marks/wu-sama-geometry.ts","../src/marks/WuSamaMark.tsx"],"sourcesContent":["/**\n * The Wu-sama mark's geometry — the founder's byline mark. **Original mark, inspired by, not derived from**: it is the\n * Krizaka hexagon (a pointy-top regular hexagon in the 400×400 frame of the family), split at its top and bottom\n * vertices into two halves like the Krizaka shield that opens at one vertex, around a W of five straight legs whose\n * points are measured on that hexagon (`u`, its half-width, and `radius`) — see `wu-sama-geometry` tests. It is not\n * the Wu-Tang Clan's mark: no bat-wing silhouette, no curve, no black-and-yellow composition. The gold is one fixed\n * mid-tone amber (≥ 3:1 on the page surfaces of both themes), a hip-hop nod and not that clan's yellow.\n */\nconst round = (n: number) => Math.round(n * 10) / 10;\nconst center = 200;\nconst radius = 150;\n/** Half the hexagon's width. */\nconst u = (radius * Math.sqrt(3)) / 2;\nconst gap = 10;\n\n/** T, UR, LR, B, LL, UL. */\nconst hexagon = [\n [center, center - radius],\n [round(center + u), center - radius / 2],\n [round(center + u), center + radius / 2],\n [center, center + radius],\n [round(center - u), center + radius / 2],\n [round(center - u), center - radius / 2],\n] as const;\nconst [T, UR, LR, B, LL, UL] = hexagon;\n\n/** The point of the edge a→b whose x is `x`. */\nconst onEdge = (a: readonly [number, number], b: readonly [number, number], x: number) => [x, round(a[1] + ((x - a[0]) / (b[0] - a[0])) * (b[1] - a[1]))] as const;\nconst pt = ([x, y]: readonly [number, number]) => `${x},${y}`;\n\nconst left = [onEdge(T, UL, center - gap), UL, LL, onEdge(B, LL, center - gap)] as const;\nconst right = [onEdge(T, UR, center + gap), UR, LR, onEdge(B, LR, center + gap)] as const;\n\n/** The W: tips and valleys at fixed fractions of the hexagon's half-width and radius; the middle summit on the axis. */\nconst wPoints = [\n [round(center - 0.63 * u), round(center - 0.4 * radius)],\n [round(center - 0.37 * u), round(center + 0.55 * radius)],\n [center, round(center - 0.03 * radius)],\n [round(center + 0.37 * u), round(center + 0.55 * radius)],\n [round(center + 0.63 * u), round(center - 0.4 * radius)],\n] as const;\nconst peak = wPoints[2];\n\nexport const WU_SAMA = {\n viewBox: \"0 0 400 400\",\n croppedViewBox: \"34 34 332 332\",\n center,\n radius,\n gap,\n hexagon,\n /** The two halves of the hexagon (open at the top and bottom vertices), stroked in ink. */\n shell: { left: `M${left.map(pt).join(\" L\")}`, right: `M${right.map(pt).join(\" L\")}`, stroke: 22 },\n /** The W, stroked in gold. */\n w: `M${wPoints.map(pt).join(\" L\")}`,\n wStroke: 26,\n /** The node: the family's lit node, a small diamond at the W's middle summit, in ink. */\n node: `M${center},${round(peak[1] - 24)} L${center + 18},${peak[1]} L${center},${round(peak[1] + 24)} L${center - 18},${peak[1]}Z`,\n /** One mid-tone amber, hsl(40 94% 37%): 3.3:1 on white and 5.8:1 on the dark surface. */\n gold: \"hsl(40 94% 37%)\",\n} as const;\n","import { a11y, type MarkProps, neutral } from \"./shared\";\nimport { WU_SAMA as G } from \"./wu-sama-geometry\";\n\n/**\n * The Wu-sama mark — the founder's byline mark, for the person and not the company (the company keeps\n * `KrizakaLogo`). Oussama's nickname is Wu-sama: a W of five straight legs in gold inside the Krizaka hexagon, split\n * at its top and bottom vertices, a small lit node at the middle summit. Still: no orbit, no pulse. The hexagon and the\n * node read the host's text role, so they are ink in both themes; the gold is one mid-tone amber that reads on both.\n *\n * **Original mark, inspired by, not derived from**: it nods to the culture its name comes from but is built from the\n * Krizaka hexagon's own measures (see `wu-sama-geometry.ts` and its tests), never from the Wu-Tang Clan's registered\n * logo — no bat-wing W, no curve, no yellow-on-black copy. Below 48 px it crops to the emblem.\n */\nexport function WuSamaMark({ size = 32, title, className }: Omit<MarkProps, \"animated\"> & { animated?: boolean }) {\n const ink = neutral(\"--kz-text-primary\", 92);\n return (\n <svg width={size} height={size} viewBox={size < 48 ? G.croppedViewBox : G.viewBox} fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" className={className} {...a11y(title)}>\n <path d={G.shell.left} stroke={ink} strokeWidth={G.shell.stroke} strokeLinejoin=\"miter\" strokeLinecap=\"butt\" />\n <path d={G.shell.right} stroke={ink} strokeWidth={G.shell.stroke} strokeLinejoin=\"miter\" strokeLinecap=\"butt\" />\n <path d={G.w} stroke={G.gold} strokeWidth={G.wStroke} strokeLinejoin=\"miter\" strokeMiterlimit={4} strokeLinecap=\"butt\" />\n <path d={G.node} fill={ink} />\n </svg>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAQA,IAAM,QAAQ,CAAC,MAAc,KAAK,MAAM,IAAI,EAAE,IAAI;AAClD,IAAM,SAAS;AACf,IAAM,SAAS;AAEf,IAAM,IAAK,SAAS,KAAK,KAAK,CAAC,IAAK;AACpC,IAAM,MAAM;AAGZ,IAAM,UAAU;AAAA,EACd,CAAC,QAAQ,SAAS,MAAM;AAAA,EACxB,CAAC,MAAM,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AAAA,EACvC,CAAC,MAAM,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AAAA,EACvC,CAAC,QAAQ,SAAS,MAAM;AAAA,EACxB,CAAC,MAAM,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AAAA,EACvC,CAAC,MAAM,SAAS,CAAC,GAAG,SAAS,SAAS,CAAC;AACzC;AACA,IAAM,CAAC,GAAG,IAAI,IAAI,GAAG,IAAI,EAAE,IAAI;AAG/B,IAAM,SAAS,CAAC,GAA8B,GAA8B,MAAc,CAAC,GAAG,MAAM,EAAE,CAAC,KAAM,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;AACxJ,IAAM,KAAK,CAAC,CAAC,GAAG,CAAC,MAAiC,GAAG,CAAC,IAAI,CAAC;AAE3D,IAAM,OAAO,CAAC,OAAO,GAAG,IAAI,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,GAAG,IAAI,SAAS,GAAG,CAAC;AAC9E,IAAM,QAAQ,CAAC,OAAO,GAAG,IAAI,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,GAAG,IAAI,SAAS,GAAG,CAAC;AAG/E,IAAM,UAAU;AAAA,EACd,CAAC,MAAM,SAAS,OAAO,CAAC,GAAG,MAAM,SAAS,MAAM,MAAM,CAAC;AAAA,EACvD,CAAC,MAAM,SAAS,OAAO,CAAC,GAAG,MAAM,SAAS,OAAO,MAAM,CAAC;AAAA,EACxD,CAAC,QAAQ,MAAM,SAAS,OAAO,MAAM,CAAC;AAAA,EACtC,CAAC,MAAM,SAAS,OAAO,CAAC,GAAG,MAAM,SAAS,OAAO,MAAM,CAAC;AAAA,EACxD,CAAC,MAAM,SAAS,OAAO,CAAC,GAAG,MAAM,SAAS,MAAM,MAAM,CAAC;AACzD;AACA,IAAM,OAAO,QAAQ,CAAC;AAEf,IAAM,UAAU;AAAA,EACrB,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,IAAI,OAAO,IAAI,MAAM,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,IAAI,QAAQ,GAAG;AAAA;AAAA,EAEhG,GAAG,IAAI,QAAQ,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,EACjC,SAAS;AAAA;AAAA,EAET,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,EAAE,IAAI,KAAK,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,EAAE,IAAI,KAAK,CAAC,CAAC;AAAA;AAAA,EAE/H,MAAM;AACR;;;AC3CI,SACE,KADF;AAHG,SAAS,WAAW,EAAE,OAAO,IAAI,OAAO,UAAU,GAAyD;AAChH,QAAM,MAAM,QAAQ,qBAAqB,EAAE;AAC3C,SACE,qBAAC,SAAI,OAAO,MAAM,QAAQ,MAAM,SAAS,OAAO,KAAK,QAAE,iBAAiB,QAAE,SAAS,MAAK,QAAO,OAAM,8BAA6B,WAAuB,GAAG,KAAK,KAAK,GACpK;AAAA,wBAAC,UAAK,GAAG,QAAE,MAAM,MAAM,QAAQ,KAAK,aAAa,QAAE,MAAM,QAAQ,gBAAe,SAAQ,eAAc,QAAO;AAAA,IAC7G,oBAAC,UAAK,GAAG,QAAE,MAAM,OAAO,QAAQ,KAAK,aAAa,QAAE,MAAM,QAAQ,gBAAe,SAAQ,eAAc,QAAO;AAAA,IAC9G,oBAAC,UAAK,GAAG,QAAE,GAAG,QAAQ,QAAE,MAAM,aAAa,QAAE,SAAS,gBAAe,SAAQ,kBAAkB,GAAG,eAAc,QAAO;AAAA,IACvH,oBAAC,UAAK,GAAG,QAAE,MAAM,MAAM,KAAK;AAAA,KAC9B;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/marks/wu-sama-geometry.ts","../src/marks/WuSamaMark.tsx"],"sourcesContent":["import { marks } from \"@krizaka/tokens/native\";\n\n/**\n * The Wu-sama mark's geometry — the founder's byline mark.\n * It shares the Krizaka shield contour (pointy-top hexagonal shield with open vertex and lit node)\n * and brand colors, holding a W of five straight legs in Krizaka blue at its center.\n */\nexport const WU_SAMA = {\n viewBox: \"0 0 400 400\",\n croppedViewBox: \"86 82 228 228\",\n offset: 20,\n /** The shield: the Krizaka pointy-top hexagon (r 92 around 180,180), open at its upper-right edge. */\n shield: \"M259.7,134 L259.7,226 L180,272 L100.3,226 L100.3,134 L180,88 L212,106.5\",\n stroke: 22,\n ink: { x1: 70, y1: 290, x2: 290, y2: 70 },\n blue: { x1: 180, y1: 180, x2: 300, y2: 60, stops: marks.krizaka },\n /** The vertex where the shield opens: a lit node in Krizaka blue. */\n node: { cx: 259.7, cy: 134, r: 19, inner: 6 },\n /** The W: five straight legs in Krizaka blue. */\n w: \"M132,142 L154,216 L180,166 L206,216 L228,142\",\n wStroke: 18,\n highlight: \"#dbeafe\",\n glow: { color: \"#196df5\", opacity: 0.16 },\n orbit: { r: 160, dash: \"8 8\", width: 1.5 },\n ring: { r: 134, width: 1 },\n} as const;\n","import { a11y, type MarkProps, neutral, useIds } from \"./shared\";\nimport { WU_SAMA as G } from \"./wu-sama-geometry\";\n\n/**\n * The Wu-sama mark — the founder's byline mark, for the person and not the company (the company keeps `KrizakaLogo`).\n * Oussama's nickname is Wu-sama: it shares Krizaka's hexagonal shield contour and color palette (ink shield, open\n * vertex with lit blue node), with the W rendered in Krizaka blue at the center. Below 48 px it crops to the emblem.\n */\nexport function WuSamaMark({ size = 32, title, className }: Omit<MarkProps, \"animated\"> & { animated?: boolean }) {\n const id = useIds(\"wsm\", [\"ink\", \"blue\", \"glow\"] as const);\n return (\n <svg width={size} height={size} viewBox={size < 48 ? G.croppedViewBox : G.viewBox} fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" className={className} {...a11y(title)}>\n <defs>\n <linearGradient id={id.ink} gradientUnits=\"userSpaceOnUse\" x1={G.ink.x1} y1={G.ink.y1} x2={G.ink.x2} y2={G.ink.y2}>\n <stop offset=\"0%\" stopColor={neutral(\"--kz-text-secondary\", 60)} />\n <stop offset=\"100%\" stopColor={neutral(\"--kz-text-primary\", 92)} />\n </linearGradient>\n <linearGradient id={id.blue} gradientUnits=\"userSpaceOnUse\" x1={G.blue.x1} y1={G.blue.y1} x2={G.blue.x2} y2={G.blue.y2}>\n {G.blue.stops.map(([offset, color]) => (\n <stop key={offset} offset={offset} stopColor={color} />\n ))}\n </linearGradient>\n <radialGradient id={id.glow} cx=\"50%\" cy=\"50%\" r=\"50%\">\n <stop offset=\"0%\" stopColor={G.glow.color} stopOpacity={G.glow.opacity} />\n <stop offset=\"100%\" stopColor={G.glow.color} stopOpacity=\"0\" />\n </radialGradient>\n </defs>\n {size >= 48 ? <circle cx=\"200\" cy=\"200\" r=\"190\" fill={`url(#${id.glow})`} /> : null}\n {size >= 48 ? (\n <>\n <circle cx=\"200\" cy=\"200\" r={G.orbit.r} stroke={neutral(\"--kz-border-strong\", 40)} strokeWidth={G.orbit.width} strokeDasharray={G.orbit.dash} opacity=\".6\" />\n <circle cx=\"200\" cy=\"200\" r={G.ring.r} stroke={neutral(\"--kz-border-default\", 30)} strokeWidth={G.ring.width} opacity=\".35\" />\n </>\n ) : null}\n <g transform={`translate(${G.offset} ${G.offset})`}>\n <path d={G.shield} stroke={`url(#${id.ink})`} strokeWidth={G.stroke} strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <circle cx={G.node.cx} cy={G.node.cy} r={G.node.r} fill={`url(#${id.blue})`} />\n <circle cx={G.node.cx} cy={G.node.cy} r={G.node.inner} fill={G.highlight} />\n <path d={G.w} stroke={`url(#${id.blue})`} strokeWidth={G.wStroke} strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </g>\n </svg>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AAOf,IAAM,UAAU;AAAA,EACrB,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,QAAQ;AAAA;AAAA,EAER,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG;AAAA,EACxC,MAAM,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,OAAO,MAAM,QAAQ;AAAA;AAAA,EAEhE,MAAM,EAAE,IAAI,OAAO,IAAI,KAAK,GAAG,IAAI,OAAO,EAAE;AAAA;AAAA,EAE5C,GAAG;AAAA,EACH,SAAS;AAAA,EACT,WAAW;AAAA,EACX,MAAM,EAAE,OAAO,WAAW,SAAS,KAAK;AAAA,EACxC,OAAO,EAAE,GAAG,KAAK,MAAM,OAAO,OAAO,IAAI;AAAA,EACzC,MAAM,EAAE,GAAG,KAAK,OAAO,EAAE;AAC3B;;;ACZQ,SAgBA,UAfE,KADF;AALD,SAAS,WAAW,EAAE,OAAO,IAAI,OAAO,UAAU,GAAyD;AAChH,QAAM,KAAK,OAAO,OAAO,CAAC,OAAO,QAAQ,MAAM,CAAU;AACzD,SACE,qBAAC,SAAI,OAAO,MAAM,QAAQ,MAAM,SAAS,OAAO,KAAK,QAAE,iBAAiB,QAAE,SAAS,MAAK,QAAO,OAAM,8BAA6B,WAAuB,GAAG,KAAK,KAAK,GACpK;AAAA,yBAAC,UACC;AAAA,2BAAC,oBAAe,IAAI,GAAG,KAAK,eAAc,kBAAiB,IAAI,QAAE,IAAI,IAAI,IAAI,QAAE,IAAI,IAAI,IAAI,QAAE,IAAI,IAAI,IAAI,QAAE,IAAI,IAC7G;AAAA,4BAAC,UAAK,QAAO,MAAK,WAAW,QAAQ,uBAAuB,EAAE,GAAG;AAAA,QACjE,oBAAC,UAAK,QAAO,QAAO,WAAW,QAAQ,qBAAqB,EAAE,GAAG;AAAA,SACnE;AAAA,MACA,oBAAC,oBAAe,IAAI,GAAG,MAAM,eAAc,kBAAiB,IAAI,QAAE,KAAK,IAAI,IAAI,QAAE,KAAK,IAAI,IAAI,QAAE,KAAK,IAAI,IAAI,QAAE,KAAK,IACjH,kBAAE,KAAK,MAAM,IAAI,CAAC,CAAC,QAAQ,KAAK,MAC/B,oBAAC,UAAkB,QAAgB,WAAW,SAAnC,MAA0C,CACtD,GACH;AAAA,MACA,qBAAC,oBAAe,IAAI,GAAG,MAAM,IAAG,OAAM,IAAG,OAAM,GAAE,OAC/C;AAAA,4BAAC,UAAK,QAAO,MAAK,WAAW,QAAE,KAAK,OAAO,aAAa,QAAE,KAAK,SAAS;AAAA,QACxE,oBAAC,UAAK,QAAO,QAAO,WAAW,QAAE,KAAK,OAAO,aAAY,KAAI;AAAA,SAC/D;AAAA,OACF;AAAA,IACC,QAAQ,KAAK,oBAAC,YAAO,IAAG,OAAM,IAAG,OAAM,GAAE,OAAM,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAK;AAAA,IAC9E,QAAQ,KACP,iCACE;AAAA,0BAAC,YAAO,IAAG,OAAM,IAAG,OAAM,GAAG,QAAE,MAAM,GAAG,QAAQ,QAAQ,sBAAsB,EAAE,GAAG,aAAa,QAAE,MAAM,OAAO,iBAAiB,QAAE,MAAM,MAAM,SAAQ,MAAK;AAAA,MAC3J,oBAAC,YAAO,IAAG,OAAM,IAAG,OAAM,GAAG,QAAE,KAAK,GAAG,QAAQ,QAAQ,uBAAuB,EAAE,GAAG,aAAa,QAAE,KAAK,OAAO,SAAQ,OAAM;AAAA,OAC9H,IACE;AAAA,IACJ,qBAAC,OAAE,WAAW,aAAa,QAAE,MAAM,IAAI,QAAE,MAAM,KAC7C;AAAA,0BAAC,UAAK,GAAG,QAAE,QAAQ,QAAQ,QAAQ,GAAG,GAAG,KAAK,aAAa,QAAE,QAAQ,eAAc,SAAQ,gBAAe,SAAQ;AAAA,MAClH,oBAAC,YAAO,IAAI,QAAE,KAAK,IAAI,IAAI,QAAE,KAAK,IAAI,GAAG,QAAE,KAAK,GAAG,MAAM,QAAQ,GAAG,IAAI,KAAK;AAAA,MAC7E,oBAAC,YAAO,IAAI,QAAE,KAAK,IAAI,IAAI,QAAE,KAAK,IAAI,GAAG,QAAE,KAAK,OAAO,MAAM,QAAE,WAAW;AAAA,MAC1E,oBAAC,UAAK,GAAG,QAAE,GAAG,QAAQ,QAAQ,GAAG,IAAI,KAAK,aAAa,QAAE,SAAS,eAAc,SAAQ,gBAAe,SAAQ;AAAA,OACjH;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,17 @@
1
+ /** A language the site speaks: its code (`fr`), its name in its own language (`Français`) and the address of the page in it. */
2
+ interface Language {
3
+ code: string;
4
+ name: string;
5
+ href: string;
6
+ }
7
+ /** The languages of the family, each named in its own language — the switch never shows “French” to a French reader. */
8
+ declare const languageNames: Readonly<Record<string, string>>;
9
+ /**
10
+ * The same page in another language: `/fr/baux?x=1#a` → `/en/baux?x=1#a`. The first segment is the language when it is
11
+ * one of `locales`; an address without a language prefix gets one. Query and hash are kept.
12
+ */
13
+ declare function languageHref(path: string, to: string, locales?: readonly string[]): string;
14
+ /** The `languages` of a switch for the page at `path`, in the order of `locales`, each named in its own language. */
15
+ declare function languagesFor(path: string, locales?: readonly string[]): Language[];
16
+
17
+ export { type Language, languageHref, languageNames, languagesFor };
@@ -0,0 +1,26 @@
1
+ // src/language-switch/href.ts
2
+ var languageNames = {
3
+ en: "English",
4
+ fr: "Fran\xE7ais",
5
+ es: "Espa\xF1ol",
6
+ de: "Deutsch",
7
+ it: "Italiano",
8
+ pt: "Portugu\xEAs"
9
+ };
10
+ function languageHref(path, to, locales = ["en", "fr"]) {
11
+ const splitIndex = path.search(/[?#]/);
12
+ const pathname = splitIndex === -1 ? path : path.slice(0, splitIndex);
13
+ const rest = splitIndex === -1 ? "" : path.slice(splitIndex);
14
+ const segments = (pathname || "/").split("/").filter(Boolean);
15
+ if (segments[0] && locales.includes(segments[0])) segments.shift();
16
+ return `/${[to, ...segments].join("/")}${rest}`;
17
+ }
18
+ function languagesFor(path, locales = ["en", "fr"]) {
19
+ return locales.map((code) => ({ code, name: languageNames[code] ?? code.toUpperCase(), href: languageHref(path, code, locales) }));
20
+ }
21
+ export {
22
+ languageHref,
23
+ languageNames,
24
+ languagesFor
25
+ };
26
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/language-switch/href.ts"],"sourcesContent":["/** A language the site speaks: its code (`fr`), its name in its own language (`Français`) and the address of the page in it. */\nexport interface Language {\n code: string;\n name: string;\n href: string;\n}\n\n/** The languages of the family, each named in its own language — the switch never shows “French” to a French reader. */\nexport const languageNames: Readonly<Record<string, string>> = {\n en: \"English\",\n fr: \"Français\",\n es: \"Español\",\n de: \"Deutsch\",\n it: \"Italiano\",\n pt: \"Português\",\n};\n\n/**\n * The same page in another language: `/fr/baux?x=1#a` → `/en/baux?x=1#a`. The first segment is the language when it is\n * one of `locales`; an address without a language prefix gets one. Query and hash are kept.\n */\nexport function languageHref(path: string, to: string, locales: readonly string[] = [\"en\", \"fr\"]): string {\n const splitIndex = path.search(/[?#]/);\n const pathname = splitIndex === -1 ? path : path.slice(0, splitIndex);\n const rest = splitIndex === -1 ? \"\" : path.slice(splitIndex);\n const segments = (pathname || \"/\").split(\"/\").filter(Boolean);\n if (segments[0] && locales.includes(segments[0])) segments.shift();\n return `/${[to, ...segments].join(\"/\")}${rest}`;\n}\n\n/** The `languages` of a switch for the page at `path`, in the order of `locales`, each named in its own language. */\nexport function languagesFor(path: string, locales: readonly string[] = [\"en\", \"fr\"]): Language[] {\n return locales.map((code) => ({ code, name: languageNames[code] ?? code.toUpperCase(), href: languageHref(path, code, locales) }));\n}\n"],"mappings":";AAQO,IAAM,gBAAkD;AAAA,EAC7D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAMO,SAAS,aAAa,MAAc,IAAY,UAA6B,CAAC,MAAM,IAAI,GAAW;AACxG,QAAM,aAAa,KAAK,OAAO,MAAM;AACrC,QAAM,WAAW,eAAe,KAAK,OAAO,KAAK,MAAM,GAAG,UAAU;AACpE,QAAM,OAAO,eAAe,KAAK,KAAK,KAAK,MAAM,UAAU;AAC3D,QAAM,YAAY,YAAY,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5D,MAAI,SAAS,CAAC,KAAK,QAAQ,SAAS,SAAS,CAAC,CAAC,EAAG,UAAS,MAAM;AACjE,SAAO,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,KAAK,GAAG,CAAC,GAAG,IAAI;AAC/C;AAGO,SAAS,aAAa,MAAc,UAA6B,CAAC,MAAM,IAAI,GAAe;AAChG,SAAO,QAAQ,IAAI,CAAC,UAAU,EAAE,MAAM,MAAM,cAAc,IAAI,KAAK,KAAK,YAAY,GAAG,MAAM,aAAa,MAAM,MAAM,OAAO,EAAE,EAAE;AACnI;","names":[]}
@@ -0,0 +1,120 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ /** A language the site speaks: its code (`fr`), its name in its own language (`Français`) and the address of the page in it. */
5
+ interface Language {
6
+ code: string;
7
+ name: string;
8
+ href: string;
9
+ }
10
+ /** The languages of the family, each named in its own language — the switch never shows “French” to a French reader. */
11
+ declare const languageNames: Readonly<Record<string, string>>;
12
+ /**
13
+ * The same page in another language: `/fr/baux?x=1#a` → `/en/baux?x=1#a`. The first segment is the language when it is
14
+ * one of `locales`; an address without a language prefix gets one. Query and hash are kept.
15
+ */
16
+ declare function languageHref(path: string, to: string, locales?: readonly string[]): string;
17
+ /** The `languages` of a switch for the page at `path`, in the order of `locales`, each named in its own language. */
18
+ declare function languagesFor(path: string, locales?: readonly string[]): Language[];
19
+
20
+ declare const languageSwitch: tailwind_variants.TVReturnType<{
21
+ [key: string]: {
22
+ [key: string]: tailwind_variants.ClassValue | {
23
+ heading?: tailwind_variants.ClassValue;
24
+ root?: tailwind_variants.ClassValue;
25
+ glyph?: tailwind_variants.ClassValue;
26
+ panel?: tailwind_variants.ClassValue;
27
+ check?: tailwind_variants.ClassValue;
28
+ inline?: tailwind_variants.ClassValue;
29
+ trigger?: tailwind_variants.ClassValue;
30
+ item?: tailwind_variants.ClassValue;
31
+ inlineLink?: tailwind_variants.ClassValue;
32
+ };
33
+ };
34
+ } | {
35
+ [x: string]: {
36
+ [x: string]: tailwind_variants.ClassValue | {
37
+ heading?: tailwind_variants.ClassValue;
38
+ root?: tailwind_variants.ClassValue;
39
+ glyph?: tailwind_variants.ClassValue;
40
+ panel?: tailwind_variants.ClassValue;
41
+ check?: tailwind_variants.ClassValue;
42
+ inline?: tailwind_variants.ClassValue;
43
+ trigger?: tailwind_variants.ClassValue;
44
+ item?: tailwind_variants.ClassValue;
45
+ inlineLink?: tailwind_variants.ClassValue;
46
+ };
47
+ };
48
+ } | {}, {
49
+ root: string;
50
+ trigger: string;
51
+ glyph: string;
52
+ panel: string;
53
+ heading: string;
54
+ item: string;
55
+ check: string;
56
+ inline: string;
57
+ inlineLink: string;
58
+ }, undefined, {
59
+ [key: string]: {
60
+ [key: string]: tailwind_variants.ClassValue | {
61
+ heading?: tailwind_variants.ClassValue;
62
+ root?: tailwind_variants.ClassValue;
63
+ glyph?: tailwind_variants.ClassValue;
64
+ panel?: tailwind_variants.ClassValue;
65
+ check?: tailwind_variants.ClassValue;
66
+ inline?: tailwind_variants.ClassValue;
67
+ trigger?: tailwind_variants.ClassValue;
68
+ item?: tailwind_variants.ClassValue;
69
+ inlineLink?: tailwind_variants.ClassValue;
70
+ };
71
+ };
72
+ } | {}, {
73
+ root: string;
74
+ trigger: string;
75
+ glyph: string;
76
+ panel: string;
77
+ heading: string;
78
+ item: string;
79
+ check: string;
80
+ inline: string;
81
+ inlineLink: string;
82
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
83
+ root: string;
84
+ trigger: string;
85
+ glyph: string;
86
+ panel: string;
87
+ heading: string;
88
+ item: string;
89
+ check: string;
90
+ inline: string;
91
+ inlineLink: string;
92
+ }>>;
93
+ type LanguageSwitchProps = {
94
+ /** The control's accessible name (“Language”, “Langue”) — passed translated. */
95
+ label: string;
96
+ /** The code of the page's language (`fr`). */
97
+ current: string;
98
+ /** The languages offered, each with its name in its own language and the address of the same page (`languagesFor`). */
99
+ languages: readonly Language[];
100
+ /**
101
+ * `menu`: a globe and the code, opening a menu (the bar). `inline`: every language in a row (a mobile panel, a settings page).
102
+ * @default "menu"
103
+ */
104
+ variant?: "menu" | "inline";
105
+ /** Your router's `<Link>` (it receives `href`, `hrefLang`, `lang`). A plain `<a>` otherwise. */
106
+ linkAs?: React.ElementType;
107
+ /** Opens the menu at first render (a story, a screenshot). */
108
+ defaultOpen?: boolean;
109
+ /** Classes of the control. */
110
+ className?: string;
111
+ };
112
+ /**
113
+ * The language switch, the same on every Krizaka site and app: a compact control — a globe and the current code
114
+ * (`FR`) — that opens a menu of the languages named in their own language (Français · English), each a link with
115
+ * `hreflang` to the same page. It shows the language you are in, never the “other” one. `variant="inline"` lays the
116
+ * languages in a row for a phone's panel or a settings page.
117
+ */
118
+ declare function LanguageSwitch({ label, current, languages, variant, linkAs, defaultOpen, className }: LanguageSwitchProps): React.JSX.Element;
119
+
120
+ export { type Language, LanguageSwitch, type LanguageSwitchProps, languageHref, languageNames, languageSwitch, languagesFor };
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import {
3
+ LanguageSwitch,
4
+ languageSwitch
5
+ } from "./chunk-3S4GHSPZ.js";
6
+
7
+ // src/language-switch/href.ts
8
+ var languageNames = {
9
+ en: "English",
10
+ fr: "Fran\xE7ais",
11
+ es: "Espa\xF1ol",
12
+ de: "Deutsch",
13
+ it: "Italiano",
14
+ pt: "Portugu\xEAs"
15
+ };
16
+ function languageHref(path, to, locales = ["en", "fr"]) {
17
+ const splitIndex = path.search(/[?#]/);
18
+ const pathname = splitIndex === -1 ? path : path.slice(0, splitIndex);
19
+ const rest = splitIndex === -1 ? "" : path.slice(splitIndex);
20
+ const segments = (pathname || "/").split("/").filter(Boolean);
21
+ if (segments[0] && locales.includes(segments[0])) segments.shift();
22
+ return `/${[to, ...segments].join("/")}${rest}`;
23
+ }
24
+ function languagesFor(path, locales = ["en", "fr"]) {
25
+ return locales.map((code) => ({ code, name: languageNames[code] ?? code.toUpperCase(), href: languageHref(path, code, locales) }));
26
+ }
27
+ export {
28
+ LanguageSwitch,
29
+ languageHref,
30
+ languageNames,
31
+ languageSwitch,
32
+ languagesFor
33
+ };
34
+ //# sourceMappingURL=language-switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/language-switch/href.ts"],"sourcesContent":["/** A language the site speaks: its code (`fr`), its name in its own language (`Français`) and the address of the page in it. */\nexport interface Language {\n code: string;\n name: string;\n href: string;\n}\n\n/** The languages of the family, each named in its own language — the switch never shows “French” to a French reader. */\nexport const languageNames: Readonly<Record<string, string>> = {\n en: \"English\",\n fr: \"Français\",\n es: \"Español\",\n de: \"Deutsch\",\n it: \"Italiano\",\n pt: \"Português\",\n};\n\n/**\n * The same page in another language: `/fr/baux?x=1#a` → `/en/baux?x=1#a`. The first segment is the language when it is\n * one of `locales`; an address without a language prefix gets one. Query and hash are kept.\n */\nexport function languageHref(path: string, to: string, locales: readonly string[] = [\"en\", \"fr\"]): string {\n const splitIndex = path.search(/[?#]/);\n const pathname = splitIndex === -1 ? path : path.slice(0, splitIndex);\n const rest = splitIndex === -1 ? \"\" : path.slice(splitIndex);\n const segments = (pathname || \"/\").split(\"/\").filter(Boolean);\n if (segments[0] && locales.includes(segments[0])) segments.shift();\n return `/${[to, ...segments].join(\"/\")}${rest}`;\n}\n\n/** The `languages` of a switch for the page at `path`, in the order of `locales`, each named in its own language. */\nexport function languagesFor(path: string, locales: readonly string[] = [\"en\", \"fr\"]): Language[] {\n return locales.map((code) => ({ code, name: languageNames[code] ?? code.toUpperCase(), href: languageHref(path, code, locales) }));\n}\n"],"mappings":";;;;;;;AAQO,IAAM,gBAAkD;AAAA,EAC7D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAMO,SAAS,aAAa,MAAc,IAAY,UAA6B,CAAC,MAAM,IAAI,GAAW;AACxG,QAAM,aAAa,KAAK,OAAO,MAAM;AACrC,QAAM,WAAW,eAAe,KAAK,OAAO,KAAK,MAAM,GAAG,UAAU;AACpE,QAAM,OAAO,eAAe,KAAK,KAAK,KAAK,MAAM,UAAU;AAC3D,QAAM,YAAY,YAAY,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5D,MAAI,SAAS,CAAC,KAAK,QAAQ,SAAS,SAAS,CAAC,CAAC,EAAG,UAAS,MAAM;AACjE,SAAO,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,KAAK,GAAG,CAAC,GAAG,IAAI;AAC/C;AAGO,SAAS,aAAa,MAAc,UAA6B,CAAC,MAAM,IAAI,GAAe;AAChG,SAAO,QAAQ,IAAI,CAAC,UAAU,EAAE,MAAM,MAAM,cAAc,IAAI,KAAK,KAAK,YAAY,GAAG,MAAM,aAAa,MAAM,MAAM,OAAO,EAAE,EAAE;AACnI;","names":[]}
package/dist/nav-bar.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as tailwind_variants from 'tailwind-variants';
2
2
  import { NavigationMenu } from 'radix-ui';
3
3
  import * as React from 'react';
4
+ import { LanguageSwitchProps } from './language-switch.js';
4
5
  import { S as SiteId, F as FamilyLabels } from './sites-CHp_vELn.js';
5
6
 
6
7
  declare const navBar: tailwind_variants.TVReturnType<{
@@ -181,9 +182,19 @@ type NavBarMenuProps = Omit<React.ComponentProps<typeof NavigationMenu.Item>, "c
181
182
  * @default 1
182
183
  */
183
184
  columns?: 1 | 2;
185
+ /**
186
+ * A section with this many links or fewer needs no hidden list: they sit in the bar as plain links (the active one
187
+ * marked, no dropdown, `label` unused on the desktop). Above it, a dropdown. `0` always makes a dropdown.
188
+ * @default 3
189
+ */
190
+ inlineUpTo?: number;
184
191
  };
185
- /** A menu of the bar: its trigger, and its links in a panel that opens under the bar. */
186
- declare function NavBarMenu({ label, active, columns, children, className, ...props }: NavBarMenuProps): React.JSX.Element;
192
+ /**
193
+ * A menu of the bar: its trigger, and its links in a panel that opens under the bar. A menu of `inlineUpTo` links or
194
+ * fewer (3 by default) is not a menu at all: its links stand in the bar, each with its active state — a hidden list of
195
+ * three is one click more for nothing. The phone's panel groups them as usual (`NavBar.MobileGroup`).
196
+ */
197
+ declare function NavBarMenu({ label, active, columns, inlineUpTo, children, className, ...props }: NavBarMenuProps): React.JSX.Element;
187
198
  type NavBarMenuLinkProps = Omit<React.ComponentProps<typeof NavigationMenu.Link>, "title" | "active"> & {
188
199
  /** The link's name — passed translated. */
189
200
  title: string;
@@ -252,6 +263,18 @@ type NavBarBadgeProps = React.ComponentProps<"span"> & {
252
263
  };
253
264
  /** A small mono badge beside the brand: the environment and the version (`DEV · v1.2.3`). Hidden below `sm`. */
254
265
  declare function NavBarBadge({ env, version, className, children, ...props }: NavBarBadgeProps): React.JSX.Element;
266
+ type NavBarLanguageProps = Omit<LanguageSwitchProps, "variant">;
267
+ /**
268
+ * The language switch, the same on every site: in the bar a globe and the current code (FR) opening a short menu of
269
+ * the languages by their own names; inside `NavBar.Mobile` the same languages as a row in the preferences.
270
+ */
271
+ declare function NavBarLanguage(props: NavBarLanguageProps): React.JSX.Element;
272
+ type NavBarMobilePreferencesProps = Omit<React.ComponentProps<"div">, "title"> & {
273
+ /** The group's heading (“Preferences”) — passed translated. */
274
+ label: string;
275
+ };
276
+ /** The last group of the mobile panel: the preferences (theme, `NavBar.Language`), in a row under their heading. */
277
+ declare function NavBarMobilePreferences({ label, className, children, ...props }: NavBarMobilePreferencesProps): React.JSX.Element;
255
278
  type NavBarRepoProps = Omit<React.ComponentProps<"a">, "children"> & {
256
279
  /** The repository the site is built from. */
257
280
  href: string;
@@ -261,7 +284,7 @@ type NavBarRepoProps = Omit<React.ComponentProps<"a">, "children"> & {
261
284
  /** The site's repository on GitHub, an icon link of `NavBar.Actions`. */
262
285
  declare function NavBarRepo({ label, className, ...props }: NavBarRepoProps): React.JSX.Element;
263
286
  /**
264
- * `NavBar.Root/Brand/Family/Badge/Items/Link/Menu/MenuLink/Actions/Repo/Mobile/MobileGroup/MobileLink` — the Krizaka navigation bar,
287
+ * `NavBar.Root/Brand/Family/Badge/Items/Link/Menu/MenuLink/Actions/Repo/Language/Mobile/MobileGroup/MobilePreferences/MobileLink` — the Krizaka navigation bar,
265
288
  * the same on every site of the family: floating, tightening on scroll, the family switcher on the brand, one light
266
289
  * gliding between its items, accessible menus, a mobile panel.
267
290
  */
@@ -276,9 +299,34 @@ declare const NavBar: {
276
299
  MenuLink: typeof NavBarMenuLink;
277
300
  Actions: typeof NavBarActions;
278
301
  Repo: typeof NavBarRepo;
302
+ Language: typeof NavBarLanguage;
279
303
  Mobile: typeof NavBarMobile;
304
+ MobilePreferences: typeof NavBarMobilePreferences;
280
305
  MobileGroup: typeof NavBarMobileGroup;
281
306
  MobileLink: typeof NavBarMobileLink;
282
307
  };
283
308
 
284
- export { NavBar, NavBarActions, NavBarBadge, type NavBarBadgeProps, NavBarBrand, type NavBarBrandProps, NavBarFamily, type NavBarFamilyProps, NavBarItems, type NavBarItemsProps, NavBarLink, type NavBarLinkProps, NavBarMenu, NavBarMenuLink, type NavBarMenuLinkProps, type NavBarMenuProps, NavBarMobile, NavBarMobileGroup, type NavBarMobileGroupProps, NavBarMobileLink, type NavBarMobileLinkProps, type NavBarMobileProps, NavBarRepo, type NavBarRepoProps, NavBarRoot, type NavBarRootProps, navBar };
309
+ /**
310
+ * Where a menu panel of the bar sits: its left edge under its trigger's, pushed back inside the page when it would run
311
+ * past the right edge, never closer to the left edge than the gutter. All values are pixels of the page (a bounding
312
+ * rect's `left`, a width), the result is the panel's `left` relative to the bar's navigation (`root`). Pure, so a
313
+ * viewport of 360 px and one of 1280 px are tested without a browser.
314
+ */
315
+ interface PlacePanel {
316
+ /** The trigger's left edge. */
317
+ trigger: number;
318
+ /** The navigation's left edge (the panel is positioned inside it). */
319
+ root: number;
320
+ /** The panel's width. */
321
+ panel: number;
322
+ /** The window's width. */
323
+ window: number;
324
+ /**
325
+ * The space kept between the panel and the window's edges.
326
+ * @default 16
327
+ */
328
+ gutter?: number;
329
+ }
330
+ declare function placePanel({ trigger, root, panel, window, gutter }: PlacePanel): number;
331
+
332
+ export { NavBar, NavBarActions, NavBarBadge, type NavBarBadgeProps, NavBarBrand, type NavBarBrandProps, NavBarFamily, type NavBarFamilyProps, NavBarItems, type NavBarItemsProps, NavBarLanguage, type NavBarLanguageProps, NavBarLink, type NavBarLinkProps, NavBarMenu, NavBarMenuLink, type NavBarMenuLinkProps, type NavBarMenuProps, NavBarMobile, NavBarMobileGroup, type NavBarMobileGroupProps, NavBarMobileLink, type NavBarMobileLinkProps, NavBarMobilePreferences, type NavBarMobilePreferencesProps, type NavBarMobileProps, NavBarRepo, type NavBarRepoProps, NavBarRoot, type NavBarRootProps, type PlacePanel, navBar, placePanel };