@burojs/ui-shadcn 0.3.0 → 0.5.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 (179) hide show
  1. package/README.md +26 -7
  2. package/dist/bulk-summary-CwSd6Yjb.cjs +108 -0
  3. package/dist/bulk-summary-CwSd6Yjb.cjs.map +1 -0
  4. package/dist/bulk-summary-GxMDP4bw.js +108 -0
  5. package/dist/bulk-summary-GxMDP4bw.js.map +1 -0
  6. package/dist/button-BxnnE28H.cjs +55 -0
  7. package/dist/button-BxnnE28H.cjs.map +1 -0
  8. package/dist/button-MWVeZaqj.js +44 -0
  9. package/dist/button-MWVeZaqj.js.map +1 -0
  10. package/dist/candidates-gate-CX2PBu6l.js +63 -0
  11. package/dist/candidates-gate-CX2PBu6l.js.map +1 -0
  12. package/dist/candidates-gate-DiFI52r7.cjs +70 -0
  13. package/dist/candidates-gate-DiFI52r7.cjs.map +1 -0
  14. package/dist/candidates-relation-picker-CBsVcnPR.js +82 -0
  15. package/dist/candidates-relation-picker-CBsVcnPR.js.map +1 -0
  16. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +84 -0
  17. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +1 -0
  18. package/dist/check-confirm-dialog-BRByTFpg.cjs +1534 -0
  19. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +1 -0
  20. package/dist/check-confirm-dialog-CkaVTPT9.js +1232 -0
  21. package/dist/check-confirm-dialog-CkaVTPT9.js.map +1 -0
  22. package/dist/dialog-B_rt9S1c.js +63 -0
  23. package/dist/dialog-B_rt9S1c.js.map +1 -0
  24. package/dist/dialog-DRNUq9EA.cjs +112 -0
  25. package/dist/dialog-DRNUq9EA.cjs.map +1 -0
  26. package/dist/filter-builder-B3mZFL-K.cjs +1761 -0
  27. package/dist/filter-builder-B3mZFL-K.cjs.map +1 -0
  28. package/dist/filter-builder-DOnaXNfP.js +1605 -0
  29. package/dist/filter-builder-DOnaXNfP.js.map +1 -0
  30. package/dist/flow-runtime-B6zOHYqI.cjs +255 -0
  31. package/dist/flow-runtime-B6zOHYqI.cjs.map +1 -0
  32. package/dist/flow-runtime-D8h99FSg.js +252 -0
  33. package/dist/flow-runtime-D8h99FSg.js.map +1 -0
  34. package/dist/flow-screen-CX05b3G9.cjs +705 -0
  35. package/dist/flow-screen-CX05b3G9.cjs.map +1 -0
  36. package/dist/flow-screen-CmbARSqg.js +701 -0
  37. package/dist/flow-screen-CmbARSqg.js.map +1 -0
  38. package/dist/index.cjs +6453 -17494
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +3754 -3621
  41. package/dist/index.d.ts +3754 -3621
  42. package/dist/index.js +6217 -17219
  43. package/dist/index.js.map +1 -1
  44. package/dist/inline-flow-host-B7U1OJUe.cjs +112 -0
  45. package/dist/inline-flow-host-B7U1OJUe.cjs.map +1 -0
  46. package/dist/inline-flow-host-C3H2UpSA.js +112 -0
  47. package/dist/inline-flow-host-C3H2UpSA.js.map +1 -0
  48. package/dist/input-BI0czGyI.cjs +23 -0
  49. package/dist/input-BI0czGyI.cjs.map +1 -0
  50. package/dist/input-CUPStzZO.js +17 -0
  51. package/dist/input-CUPStzZO.js.map +1 -0
  52. package/dist/label-66W1qbke.js +29 -0
  53. package/dist/label-66W1qbke.js.map +1 -0
  54. package/dist/label-w6JYf2cF.cjs +36 -0
  55. package/dist/label-w6JYf2cF.cjs.map +1 -0
  56. package/dist/layout/theme-storage-key.cjs +5 -10
  57. package/dist/layout/theme-storage-key.cjs.map +1 -1
  58. package/dist/layout/theme-storage-key.d.cts +2 -23
  59. package/dist/layout/theme-storage-key.d.ts +2 -23
  60. package/dist/layout/theme-storage-key.js +5 -2
  61. package/dist/layout/theme-storage-key.js.map +1 -1
  62. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +14 -0
  63. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +1 -0
  64. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +19 -0
  65. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +1 -0
  66. package/dist/markdown/index.cjs +424 -511
  67. package/dist/markdown/index.cjs.map +1 -1
  68. package/dist/markdown/index.d.cts +1072 -34
  69. package/dist/markdown/index.d.ts +1072 -34
  70. package/dist/markdown/index.js +411 -459
  71. package/dist/markdown/index.js.map +1 -1
  72. package/dist/page-flow-route-CQ7HsbBm.cjs +277 -0
  73. package/dist/page-flow-route-CQ7HsbBm.cjs.map +1 -0
  74. package/dist/page-flow-route-CyXSvXSE.js +277 -0
  75. package/dist/page-flow-route-CyXSvXSE.js.map +1 -0
  76. package/dist/peek-filter-CnqHwTMU.cjs +51 -0
  77. package/dist/peek-filter-CnqHwTMU.cjs.map +1 -0
  78. package/dist/peek-filter-ErLfO153.js +28 -0
  79. package/dist/peek-filter-ErLfO153.js.map +1 -0
  80. package/dist/place-node--GdsP688.js +7315 -0
  81. package/dist/place-node--GdsP688.js.map +1 -0
  82. package/dist/place-node-SIp4XYQH.cjs +7833 -0
  83. package/dist/place-node-SIp4XYQH.cjs.map +1 -0
  84. package/dist/related-list-cards-B6x9HQQp.js +42 -0
  85. package/dist/related-list-cards-B6x9HQQp.js.map +1 -0
  86. package/dist/related-list-cards-nxuODlIA.cjs +42 -0
  87. package/dist/related-list-cards-nxuODlIA.cjs.map +1 -0
  88. package/dist/related-list-timeline-BYJKEbmA.cjs +142 -0
  89. package/dist/related-list-timeline-BYJKEbmA.cjs.map +1 -0
  90. package/dist/related-list-timeline-DEdfd-rr.js +142 -0
  91. package/dist/related-list-timeline-DEdfd-rr.js.map +1 -0
  92. package/dist/related-rows-B4levHcR.js +186 -0
  93. package/dist/related-rows-B4levHcR.js.map +1 -0
  94. package/dist/related-rows-zh5f_4QR.cjs +209 -0
  95. package/dist/related-rows-zh5f_4QR.cjs.map +1 -0
  96. package/dist/relation-create-BOaUe12G.cjs +362 -0
  97. package/dist/relation-create-BOaUe12G.cjs.map +1 -0
  98. package/dist/relation-create-Bg-eEJLs.js +337 -0
  99. package/dist/relation-create-Bg-eEJLs.js.map +1 -0
  100. package/dist/relation-many-picker-B-NCEUgX.cjs +465 -0
  101. package/dist/relation-many-picker-B-NCEUgX.cjs.map +1 -0
  102. package/dist/relation-many-picker-gdAOD-qK.js +464 -0
  103. package/dist/relation-many-picker-gdAOD-qK.js.map +1 -0
  104. package/dist/relation-picker-BAY77ivO.js +462 -0
  105. package/dist/relation-picker-BAY77ivO.js.map +1 -0
  106. package/dist/relation-picker-Da_uhFvA.cjs +479 -0
  107. package/dist/relation-picker-Da_uhFvA.cjs.map +1 -0
  108. package/dist/relation-picker-dialog-M0pQaWlp.cjs +300 -0
  109. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +1 -0
  110. package/dist/relation-picker-dialog-hA9rYrZB.js +299 -0
  111. package/dist/relation-picker-dialog-hA9rYrZB.js.map +1 -0
  112. package/dist/resource-page-router-OSQyRA5b.cjs +1779 -0
  113. package/dist/resource-page-router-OSQyRA5b.cjs.map +1 -0
  114. package/dist/resource-page-router-T4vS5gbJ.js +1582 -0
  115. package/dist/resource-page-router-T4vS5gbJ.js.map +1 -0
  116. package/dist/rich-text-DFerywgz.js +457 -0
  117. package/dist/rich-text-DFerywgz.js.map +1 -0
  118. package/dist/rich-text-vTyVjDoa.cjs +460 -0
  119. package/dist/rich-text-vTyVjDoa.cjs.map +1 -0
  120. package/dist/search-access-B7G5oR8n.cjs +812 -0
  121. package/dist/search-access-B7G5oR8n.cjs.map +1 -0
  122. package/dist/search-access-CURsWn-U.js +669 -0
  123. package/dist/search-access-CURsWn-U.js.map +1 -0
  124. package/dist/shell-BPlk8hEa.js +205 -0
  125. package/dist/shell-BPlk8hEa.js.map +1 -0
  126. package/dist/shell-DxhlsPwm.cjs +271 -0
  127. package/dist/shell-DxhlsPwm.cjs.map +1 -0
  128. package/dist/skeleton-U2noefj5.js +13 -0
  129. package/dist/skeleton-U2noefj5.js.map +1 -0
  130. package/dist/skeleton-_1gP7wan.cjs +18 -0
  131. package/dist/skeleton-_1gP7wan.cjs.map +1 -0
  132. package/dist/styles.css +255 -17
  133. package/dist/theme/theme-css.cjs +95 -96
  134. package/dist/theme/theme-css.cjs.map +1 -1
  135. package/dist/theme/theme-css.d.cts +10 -8
  136. package/dist/theme/theme-css.d.ts +10 -8
  137. package/dist/theme/theme-css.js +94 -94
  138. package/dist/theme/theme-css.js.map +1 -1
  139. package/dist/theme/theme-storage.cjs +34 -39
  140. package/dist/theme/theme-storage.cjs.map +1 -1
  141. package/dist/theme/theme-storage.d.cts +3 -1
  142. package/dist/theme/theme-storage.d.ts +3 -1
  143. package/dist/theme/theme-storage.js +33 -37
  144. package/dist/theme/theme-storage.js.map +1 -1
  145. package/dist/theme-storage-key-pYlp4aDS.d.cts +31 -0
  146. package/dist/theme-storage-key-pYlp4aDS.d.ts +31 -0
  147. package/dist/toaster-C7CiYA4Z.cjs +248 -0
  148. package/dist/toaster-C7CiYA4Z.cjs.map +1 -0
  149. package/dist/toaster-CfCRLgR-.js +164 -0
  150. package/dist/toaster-CfCRLgR-.js.map +1 -0
  151. package/dist/use-dialog-filter-state-BBCC0OEK.cjs +92 -0
  152. package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +1 -0
  153. package/dist/use-dialog-filter-state-BDcgS5Oz.js +87 -0
  154. package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +1 -0
  155. package/dist/use-theme-DFlpXils.cjs +257 -0
  156. package/dist/use-theme-DFlpXils.cjs.map +1 -0
  157. package/dist/use-theme-dnE3Od3I.js +175 -0
  158. package/dist/use-theme-dnE3Od3I.js.map +1 -0
  159. package/package.json +18 -17
  160. package/dist/chunk-ABUQPOOE.js +0 -11
  161. package/dist/chunk-ABUQPOOE.js.map +0 -1
  162. package/dist/chunk-DBGGWBFG.cjs +0 -199
  163. package/dist/chunk-DBGGWBFG.cjs.map +0 -1
  164. package/dist/chunk-FMX4GLCQ.js +0 -6
  165. package/dist/chunk-FMX4GLCQ.js.map +0 -1
  166. package/dist/chunk-UC57Z243.js +0 -143
  167. package/dist/chunk-UC57Z243.js.map +0 -1
  168. package/dist/chunk-UPGPO75B.js +0 -164
  169. package/dist/chunk-UPGPO75B.js.map +0 -1
  170. package/dist/chunk-VXJAXJ3U.cjs +0 -8
  171. package/dist/chunk-VXJAXJ3U.cjs.map +0 -1
  172. package/dist/chunk-W7AEYE7A.cjs +0 -13
  173. package/dist/chunk-W7AEYE7A.cjs.map +0 -1
  174. package/dist/chunk-YF5IW525.cjs +0 -155
  175. package/dist/chunk-YF5IW525.cjs.map +0 -1
  176. package/dist/rich-text-6V7WZ3WV.cjs +0 -518
  177. package/dist/rich-text-6V7WZ3WV.cjs.map +0 -1
  178. package/dist/rich-text-N2FZEJJV.js +0 -491
  179. package/dist/rich-text-N2FZEJJV.js.map +0 -1
@@ -1,492 +1,444 @@
1
- import { docShareUrl, useTheme, docSlug, DOC_ID_PREFIX, readDocHash, scrollToDocAnchor } from '../chunk-UC57Z243.js';
2
- export { DOC_ID_PREFIX, docShareUrl, docSlug, findDocAnchor, readDocHash, scrollToDocAnchor } from '../chunk-UC57Z243.js';
3
- import '../chunk-FMX4GLCQ.js';
4
- import { cn } from '../chunk-ABUQPOOE.js';
5
- import Markdown from 'react-markdown';
6
- import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
7
- import rehypeSlug from 'rehype-slug';
8
- import remarkDirective from 'remark-directive';
9
- import remarkGfm from 'remark-gfm';
10
- import { useOptionalT } from '@burojs/react';
11
- import { IconCheck, IconLink, IconChevronDown } from '@tabler/icons-react';
12
- import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
13
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
14
- import { visit } from 'unist-util-visit';
15
- import * as AccordionPrimitive from '@radix-ui/react-accordion';
16
-
17
- function DocAnchorLink({
18
- slug,
19
- stopPropagation,
20
- className
21
- }) {
22
- const t = useOptionalT();
23
- const [copied, setCopied] = useState(false);
24
- const timer = useRef(null);
25
- useEffect(
26
- () => () => {
27
- if (timer.current) clearTimeout(timer.current);
28
- },
29
- []
30
- );
31
- const onClick = useCallback(
32
- (event) => {
33
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
34
- if (stopPropagation) event.stopPropagation();
35
- void navigator.clipboard?.writeText(docShareUrl(slug)).then(() => {
36
- setCopied(true);
37
- if (timer.current) clearTimeout(timer.current);
38
- timer.current = setTimeout(() => setCopied(false), 1600);
39
- }).catch(() => {
40
- });
41
- },
42
- [slug, stopPropagation]
43
- );
44
- const label = copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : t("docPanel.copyLink", { defaultValue: "Copy link to this section" });
45
- return /* @__PURE__ */ jsxs(
46
- "a",
47
- {
48
- href: `#${slug}`,
49
- onClick,
50
- title: label,
51
- "aria-label": label,
52
- "data-testid": `doc-anchor:${slug}`,
53
- "data-copied": copied ? "true" : void 0,
54
- className: cn(
55
- "ml-2 inline-flex shrink-0 items-center rounded-sm p-0.5 align-middle no-underline",
56
- "text-muted-foreground transition-opacity hover:text-foreground",
57
- // Hidden until the reader is at this heading — a permanent « # » beside
58
- // every heading reads as scaffolding. `focus-visible` keeps it
59
- // reachable by keyboard, where there is no hover to reveal it.
60
- "opacity-0 group-hover/anchor:opacity-100 focus-visible:opacity-100",
61
- "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
62
- copied && "text-primary opacity-100",
63
- className
64
- ),
65
- children: [
66
- copied ? /* @__PURE__ */ jsx(IconCheck, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(IconLink, { className: "size-3.5", "aria-hidden": "true" }),
67
- /* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : "" })
68
- ]
69
- }
70
- );
1
+ "use client";
2
+ import { a as docSlug, c as scrollToDocAnchor, i as docShareUrl, l as cn, n as useTheme, o as findDocAnchor, r as DOC_ID_PREFIX, s as readDocHash } from "../use-theme-dnE3Od3I.js";
3
+ import { useOptionalT } from "@burojs/react";
4
+ import { IconCheck, IconChevronDown, IconLink } from "@tabler/icons-react";
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
+ import Markdown from "react-markdown";
8
+ import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
9
+ import rehypeSlug from "rehype-slug";
10
+ import remarkDirective from "remark-directive";
11
+ import remarkGfm from "remark-gfm";
12
+ import { visit } from "unist-util-visit";
13
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
14
+ //#region src/markdown/anchor-link.tsx
15
+ function DocAnchorLink({ slug, stopPropagation, className }) {
16
+ const t = useOptionalT();
17
+ const [copied, setCopied] = useState(false);
18
+ const timer = useRef(null);
19
+ useEffect(() => () => {
20
+ if (timer.current) clearTimeout(timer.current);
21
+ }, []);
22
+ const onClick = useCallback((event) => {
23
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
24
+ if (stopPropagation) event.stopPropagation();
25
+ navigator.clipboard?.writeText(docShareUrl(slug)).then(() => {
26
+ setCopied(true);
27
+ if (timer.current) clearTimeout(timer.current);
28
+ timer.current = setTimeout(() => setCopied(false), 1600);
29
+ }).catch(() => {});
30
+ }, [slug, stopPropagation]);
31
+ const label = copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : t("docPanel.copyLink", { defaultValue: "Copy link to this section" });
32
+ return jsxs("a", {
33
+ href: `#${slug}`,
34
+ onClick,
35
+ title: label,
36
+ "aria-label": label,
37
+ "data-testid": `doc-anchor:${slug}`,
38
+ "data-copied": copied ? "true" : void 0,
39
+ className: cn("ml-2 inline-flex shrink-0 items-center rounded-sm p-0.5 align-middle no-underline", "text-muted-foreground transition-opacity hover:text-foreground", "opacity-0 group-hover/anchor:opacity-100 focus-visible:opacity-100", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring", copied && "text-primary opacity-100", className),
40
+ children: [copied ? jsx(IconCheck, {
41
+ className: "size-3.5",
42
+ "aria-hidden": "true"
43
+ }) : jsx(IconLink, {
44
+ className: "size-3.5",
45
+ "aria-hidden": "true"
46
+ }), jsx("span", {
47
+ role: "status",
48
+ className: "sr-only",
49
+ children: copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : ""
50
+ })]
51
+ });
71
52
  }
72
-
73
- // src/lib/css-color.ts
74
- var OKLCH = /^oklch\(\s*([^\s/]+)\s+([^\s/]+)\s+([^\s/]+)\s*(?:\/\s*([^\s/]+)\s*)?\)$/i;
75
- var KHROMA_SAFE = /^(#|rgba?\(|hsla?\(|[a-z]+$)/i;
53
+ //#endregion
54
+ //#region src/lib/css-color.ts
55
+ const OKLCH = /^oklch\(\s*([^\s/]+)\s+([^\s/]+)\s+([^\s/]+)\s*(?:\/\s*([^\s/]+)\s*)?\)$/i;
56
+ const KHROMA_SAFE = /^(#|rgba?\(|hsla?\(|[a-z]+$)/i;
76
57
  function component(raw, pct) {
77
- if (raw.toLowerCase() === "none") return 0;
78
- const percent = raw.endsWith("%");
79
- const n = Number.parseFloat(percent ? raw.slice(0, -1) : raw);
80
- if (!Number.isFinite(n)) return null;
81
- return percent ? n / 100 * pct : n;
58
+ if (raw.toLowerCase() === "none") return 0;
59
+ const percent = raw.endsWith("%");
60
+ const n = Number.parseFloat(percent ? raw.slice(0, -1) : raw);
61
+ if (!Number.isFinite(n)) return null;
62
+ return percent ? n / 100 * pct : n;
82
63
  }
83
64
  function hueDegrees(raw) {
84
- if (raw.toLowerCase() === "none") return 0;
85
- const match = /^(-?[\d.]+)(deg|rad|grad|turn)?$/i.exec(raw);
86
- if (match === null) return null;
87
- const n = Number.parseFloat(match[1]);
88
- if (!Number.isFinite(n)) return null;
89
- switch ((match[2] ?? "deg").toLowerCase()) {
90
- case "rad":
91
- return n * 180 / Math.PI;
92
- case "grad":
93
- return n * 0.9;
94
- case "turn":
95
- return n * 360;
96
- default:
97
- return n;
98
- }
65
+ if (raw.toLowerCase() === "none") return 0;
66
+ const match = /^(-?[\d.]+)(deg|rad|grad|turn)?$/i.exec(raw);
67
+ if (match === null) return null;
68
+ const n = Number.parseFloat(match[1]);
69
+ if (!Number.isFinite(n)) return null;
70
+ switch ((match[2] ?? "deg").toLowerCase()) {
71
+ case "rad": return n * 180 / Math.PI;
72
+ case "grad": return n * .9;
73
+ case "turn": return n * 360;
74
+ default: return n;
75
+ }
99
76
  }
100
77
  function encode(channel) {
101
- const v = channel <= 31308e-7 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - 0.055;
102
- return Math.round(Math.min(1, Math.max(0, v)) * 255);
78
+ const v = channel <= .0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - .055;
79
+ return Math.round(Math.min(1, Math.max(0, v)) * 255);
103
80
  }
104
81
  function hex2(value) {
105
- return value.toString(16).padStart(2, "0");
82
+ return value.toString(16).padStart(2, "0");
106
83
  }
107
84
  function oklchToHex(value) {
108
- const match = OKLCH.exec(value.trim());
109
- if (match === null) return null;
110
- const L = component(match[1], 1);
111
- const C = component(match[2], 0.4);
112
- const H = hueDegrees(match[3]);
113
- const A = match[4] === void 0 ? 1 : component(match[4], 1);
114
- if (L === null || C === null || H === null || A === null) return null;
115
- const rad = H * Math.PI / 180;
116
- const a = C * Math.cos(rad);
117
- const b = C * Math.sin(rad);
118
- const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
119
- const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
120
- const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
121
- const r = encode(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s);
122
- const g = encode(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s);
123
- const bl = encode(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s);
124
- const alpha = Math.min(1, Math.max(0, A));
125
- const suffix = alpha === 1 ? "" : hex2(Math.round(alpha * 255));
126
- return `#${hex2(r)}${hex2(g)}${hex2(bl)}${suffix}`;
85
+ const match = OKLCH.exec(value.trim());
86
+ if (match === null) return null;
87
+ const L = component(match[1], 1);
88
+ const C = component(match[2], .4);
89
+ const H = hueDegrees(match[3]);
90
+ const A = match[4] === void 0 ? 1 : component(match[4], 1);
91
+ if (L === null || C === null || H === null || A === null) return null;
92
+ const rad = H * Math.PI / 180;
93
+ const a = C * Math.cos(rad);
94
+ const b = C * Math.sin(rad);
95
+ const l = (L + .3963377774 * a + .2158037573 * b) ** 3;
96
+ const m = (L - .1055613458 * a - .0638541728 * b) ** 3;
97
+ const s = (L - .0894841775 * a - 1.291485548 * b) ** 3;
98
+ const r = encode(4.0767416621 * l - 3.3077115913 * m + .2309699292 * s);
99
+ const g = encode(-1.2684380046 * l + 2.6097574011 * m - .3413193965 * s);
100
+ const bl = encode(-.0041960863 * l - .7034186147 * m + 1.707614701 * s);
101
+ const alpha = Math.min(1, Math.max(0, A));
102
+ const suffix = alpha === 1 ? "" : hex2(Math.round(alpha * 255));
103
+ return `#${hex2(r)}${hex2(g)}${hex2(bl)}${suffix}`;
127
104
  }
128
105
  function toLegacyColor(value) {
129
- const trimmed = value.trim();
130
- if (trimmed === "") return null;
131
- if (KHROMA_SAFE.test(trimmed)) return trimmed;
132
- return oklchToHex(trimmed);
106
+ const trimmed = value.trim();
107
+ if (trimmed === "") return null;
108
+ if (KHROMA_SAFE.test(trimmed)) return trimmed;
109
+ return oklchToHex(trimmed);
133
110
  }
111
+ //#endregion
112
+ //#region src/markdown/mermaid.tsx
134
113
  function cssVar(styles, name, fallback) {
135
- return toLegacyColor(styles.getPropertyValue(name)) ?? fallback;
114
+ return toLegacyColor(styles.getPropertyValue(name)) ?? fallback;
136
115
  }
137
- var seq = 0;
116
+ let seq = 0;
138
117
  function MermaidDiagram({ code, className }) {
139
- const [svg, setSvg] = useState(null);
140
- const [failed, setFailed] = useState(null);
141
- const { resolved: theme } = useTheme();
142
- const idRef = useRef(null);
143
- idRef.current ??= `buro-mermaid-${seq += 1}`;
144
- useEffect(() => {
145
- let cancelled = false;
146
- void (async () => {
147
- try {
148
- const mermaid = (await import('mermaid')).default;
149
- const styles = getComputedStyle(document.documentElement);
150
- const dark = theme === "dark";
151
- mermaid.initialize({
152
- startOnLoad: false,
153
- securityLevel: "strict",
154
- fontFamily: "inherit",
155
- theme: "base",
156
- darkMode: dark,
157
- themeVariables: {
158
- background: cssVar(styles, "--background", dark ? "#0b0b0c" : "#ffffff"),
159
- primaryColor: cssVar(styles, "--muted", dark ? "#1c1c1f" : "#f4f4f5"),
160
- primaryTextColor: cssVar(styles, "--foreground", dark ? "#fafafa" : "#09090b"),
161
- primaryBorderColor: cssVar(styles, "--border", dark ? "#27272a" : "#e4e4e7"),
162
- lineColor: cssVar(styles, "--muted-foreground", dark ? "#a1a1aa" : "#71717a"),
163
- secondaryColor: cssVar(styles, "--secondary", dark ? "#18181b" : "#f4f4f5"),
164
- tertiaryColor: cssVar(styles, "--accent", dark ? "#18181b" : "#fafafa"),
165
- fontSize: "13px"
166
- }
167
- });
168
- await mermaid.parse(code);
169
- const { svg: out } = await mermaid.render(idRef.current, code);
170
- if (!cancelled) {
171
- setSvg(out);
172
- setFailed(null);
173
- }
174
- } catch (error) {
175
- if (!cancelled) {
176
- setSvg(null);
177
- setFailed(error instanceof Error ? error.message : String(error));
178
- }
179
- }
180
- })();
181
- return () => {
182
- cancelled = true;
183
- };
184
- }, [code, theme]);
185
- if (failed !== null) {
186
- return /* @__PURE__ */ jsx(
187
- "pre",
188
- {
189
- className: cn("overflow-x-auto rounded-md border border-dashed p-3 text-xs", className),
190
- title: failed,
191
- "data-testid": "mermaid:failed",
192
- children: /* @__PURE__ */ jsx("code", { children: code })
193
- }
194
- );
195
- }
196
- if (svg === null) {
197
- return /* @__PURE__ */ jsx(
198
- "div",
199
- {
200
- className: cn("h-24 animate-pulse rounded-md border bg-muted/40", className),
201
- "data-testid": "mermaid:loading",
202
- "aria-hidden": "true"
203
- }
204
- );
205
- }
206
- return /* @__PURE__ */ jsx(
207
- "figure",
208
- {
209
- className: cn(
210
- "not-prose my-4 overflow-x-auto rounded-md border bg-card/40 text-card-foreground p-4",
211
- // Mermaid emits an intrinsic width; letting it scale down keeps a wide
212
- // graph inside the column instead of pushing the article sideways.
213
- "[&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full",
214
- className
215
- ),
216
- "data-testid": "mermaid:diagram",
217
- dangerouslySetInnerHTML: { __html: svg }
218
- }
219
- );
118
+ const [svg, setSvg] = useState(null);
119
+ const [failed, setFailed] = useState(null);
120
+ const { resolved: theme } = useTheme();
121
+ const idRef = useRef(null);
122
+ idRef.current ??= `buro-mermaid-${seq += 1}`;
123
+ useEffect(() => {
124
+ let cancelled = false;
125
+ (async () => {
126
+ try {
127
+ const mermaid = (await import("mermaid")).default;
128
+ const styles = getComputedStyle(document.documentElement);
129
+ const dark = theme === "dark";
130
+ mermaid.initialize({
131
+ startOnLoad: false,
132
+ securityLevel: "strict",
133
+ fontFamily: "inherit",
134
+ theme: "base",
135
+ darkMode: dark,
136
+ themeVariables: {
137
+ background: cssVar(styles, "--background", dark ? "#0b0b0c" : "#ffffff"),
138
+ primaryColor: cssVar(styles, "--muted", dark ? "#1c1c1f" : "#f4f4f5"),
139
+ primaryTextColor: cssVar(styles, "--foreground", dark ? "#fafafa" : "#09090b"),
140
+ primaryBorderColor: cssVar(styles, "--border", dark ? "#27272a" : "#e4e4e7"),
141
+ lineColor: cssVar(styles, "--muted-foreground", dark ? "#a1a1aa" : "#71717a"),
142
+ secondaryColor: cssVar(styles, "--secondary", dark ? "#18181b" : "#f4f4f5"),
143
+ tertiaryColor: cssVar(styles, "--accent", dark ? "#18181b" : "#fafafa"),
144
+ fontSize: "13px"
145
+ }
146
+ });
147
+ await mermaid.parse(code);
148
+ const { svg: out } = await mermaid.render(idRef.current, code);
149
+ if (!cancelled) {
150
+ setSvg(out);
151
+ setFailed(null);
152
+ }
153
+ } catch (error) {
154
+ if (!cancelled) {
155
+ setSvg(null);
156
+ setFailed(error instanceof Error ? error.message : String(error));
157
+ }
158
+ }
159
+ })();
160
+ return () => {
161
+ cancelled = true;
162
+ };
163
+ }, [code, theme]);
164
+ if (failed !== null) return jsx("pre", {
165
+ className: cn("overflow-x-auto rounded-md border border-dashed p-3 text-xs", className),
166
+ title: failed,
167
+ "data-testid": "mermaid:failed",
168
+ children: jsx("code", { children: code })
169
+ });
170
+ if (svg === null) return jsx("div", {
171
+ className: cn("h-24 animate-pulse rounded-md border bg-muted/40", className),
172
+ "data-testid": "mermaid:loading",
173
+ "aria-hidden": "true"
174
+ });
175
+ return jsx("figure", {
176
+ className: cn("not-prose my-4 overflow-x-auto rounded-md border bg-card/40 text-card-foreground p-4", "[&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full", className),
177
+ "data-testid": "mermaid:diagram",
178
+ dangerouslySetInnerHTML: { __html: svg }
179
+ });
220
180
  }
221
- var VIDEO_ATTRIBUTES = [
222
- "src",
223
- "poster",
224
- "controls",
225
- "loop",
226
- "muted",
227
- "autoPlay",
228
- "playsInline",
229
- "preload",
230
- "width",
231
- "height"
181
+ //#endregion
182
+ //#region src/markdown/sanitize-schema.ts
183
+ const VIDEO_ATTRIBUTES = [
184
+ "src",
185
+ "poster",
186
+ "controls",
187
+ "loop",
188
+ "muted",
189
+ "autoPlay",
190
+ "playsInline",
191
+ "preload",
192
+ "width",
193
+ "height"
232
194
  ];
233
- var docSanitizeSchema = {
234
- ...defaultSchema,
235
- // `source` and `picture` are ALREADY in defaultSchema — appending them would
236
- // be a harmless duplicate, but it would also be a sign the list was never
237
- // actually read.
238
- tagNames: [...defaultSchema.tagNames ?? [], "video"],
239
- attributes: {
240
- ...defaultSchema.attributes,
241
- video: [...VIDEO_ATTRIBUTES],
242
- // defaultSchema.attributes.source is ['srcSet']. Replacing it outright
243
- // would silently break <picture>, which the default explicitly supports.
244
- source: [...defaultSchema.attributes?.source ?? [], "src", "type"],
245
- // `loading` is in neither `img` nor the `*` bucket, so lazy images need it
246
- // allowed explicitly or the attribute is stripped and every image in a
247
- // long article loads at once.
248
- img: [...defaultSchema.attributes?.img ?? [], "loading"]
249
- }
195
+ const docSanitizeSchema = {
196
+ ...defaultSchema,
197
+ tagNames: [...defaultSchema.tagNames ?? [], "video"],
198
+ attributes: {
199
+ ...defaultSchema.attributes,
200
+ video: [...VIDEO_ATTRIBUTES],
201
+ source: [
202
+ ...defaultSchema.attributes?.source ?? [],
203
+ "src",
204
+ "type"
205
+ ],
206
+ img: [...defaultSchema.attributes?.img ?? [], "loading"]
207
+ }
250
208
  };
251
- var ALLOWED = ["src", "poster", "width", "height"];
209
+ //#endregion
210
+ //#region src/markdown/video-directive.ts
211
+ const ALLOWED = [
212
+ "src",
213
+ "poster",
214
+ "width",
215
+ "height"
216
+ ];
252
217
  function remarkVideoDirective() {
253
- return (tree) => {
254
- visit(tree, (node) => {
255
- const directive = node;
256
- if (directive.type !== "leafDirective" && directive.type !== "containerDirective" && directive.type !== "textDirective") {
257
- return;
258
- }
259
- if (directive.name !== "video") return;
260
- const attrs = directive.attributes ?? {};
261
- const props = {
262
- // Always on: a video the reader cannot pause is hostile, and an
263
- // article that autoplays sound is worse.
264
- controls: true,
265
- preload: "metadata"
266
- };
267
- for (const key of ALLOWED) {
268
- const value = attrs[key];
269
- if (typeof value === "string" && value.length > 0) props[key] = value;
270
- }
271
- if (typeof props.src !== "string") return;
272
- directive.data = { ...directive.data, hName: "video", hProperties: props };
273
- });
274
- };
218
+ return (tree) => {
219
+ visit(tree, (node) => {
220
+ const directive = node;
221
+ if (directive.type !== "leafDirective" && directive.type !== "containerDirective" && directive.type !== "textDirective") return;
222
+ if (directive.name !== "video") return;
223
+ const attrs = directive.attributes ?? {};
224
+ const props = {
225
+ controls: true,
226
+ preload: "metadata"
227
+ };
228
+ for (const key of ALLOWED) {
229
+ const value = attrs[key];
230
+ if (typeof value === "string" && value.length > 0) props[key] = value;
231
+ }
232
+ if (typeof props.src !== "string") return;
233
+ directive.data = {
234
+ ...directive.data,
235
+ hName: "video",
236
+ hProperties: props
237
+ };
238
+ });
239
+ };
275
240
  }
276
- var Accordion = AccordionPrimitive.Root;
277
- function AccordionItem({
278
- className,
279
- ...props
280
- }) {
281
- return /* @__PURE__ */ jsx(
282
- AccordionPrimitive.Item,
283
- {
284
- className: cn("border-b border-border/60 last:border-b-0", className),
285
- ...props
286
- }
287
- );
241
+ //#endregion
242
+ //#region src/primitives/accordion.tsx
243
+ const Accordion = AccordionPrimitive.Root;
244
+ function AccordionItem({ className, ...props }) {
245
+ return jsx(AccordionPrimitive.Item, {
246
+ className: cn("border-b border-border/60 last:border-b-0", className),
247
+ ...props
248
+ });
288
249
  }
289
- function AccordionTrigger({
290
- className,
291
- children,
292
- ...props
293
- }) {
294
- return /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
295
- AccordionPrimitive.Trigger,
296
- {
297
- className: cn(
298
- "flex flex-1 items-start justify-between gap-3 py-3 text-left",
299
- "text-[0.9375rem] font-medium leading-snug transition-colors",
300
- "hover:text-primary focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
301
- "rounded-sm [&[data-state=open]>svg]:rotate-180",
302
- className
303
- ),
304
- ...props,
305
- children: [
306
- children,
307
- /* @__PURE__ */ jsx(
308
- IconChevronDown,
309
- {
310
- className: "mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200",
311
- "aria-hidden": "true"
312
- }
313
- )
314
- ]
315
- }
316
- ) });
250
+ function AccordionTrigger({ className, children, ...props }) {
251
+ return jsx(AccordionPrimitive.Header, {
252
+ className: "flex",
253
+ children: jsxs(AccordionPrimitive.Trigger, {
254
+ className: cn("flex flex-1 items-start justify-between gap-3 py-3 text-left", "text-[0.9375rem] font-medium leading-snug transition-colors", "hover:text-primary focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring", "rounded-sm [&[data-state=open]>svg]:rotate-180", className),
255
+ ...props,
256
+ children: [children, jsx(IconChevronDown, {
257
+ className: "mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200",
258
+ "aria-hidden": "true"
259
+ })]
260
+ })
261
+ });
317
262
  }
318
- function AccordionContent({
319
- className,
320
- children,
321
- ...props
322
- }) {
323
- return /* @__PURE__ */ jsx(
324
- AccordionPrimitive.Content,
325
- {
326
- className: cn(
327
- "overflow-hidden",
328
- "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
329
- ),
330
- ...props,
331
- children: /* @__PURE__ */ jsx("div", { className: cn("pb-3.5 pt-0", className), children })
332
- }
333
- );
263
+ function AccordionContent({ className, children, ...props }) {
264
+ return jsx(AccordionPrimitive.Content, {
265
+ className: cn("overflow-hidden", "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"),
266
+ ...props,
267
+ children: jsx("div", {
268
+ className: cn("pb-3.5 pt-0", className),
269
+ children
270
+ })
271
+ });
334
272
  }
273
+ //#endregion
274
+ //#region src/markdown/faq.tsx
335
275
  function splitFaq(markdown) {
336
- const lines = markdown.split("\n");
337
- const preamble = [];
338
- const sections = [];
339
- let current;
340
- let fence;
341
- for (const line of lines) {
342
- const fenceMatch = /^\s{0,3}(`{3,}|~{3,})/.exec(line);
343
- if (fenceMatch?.[1] !== void 0) {
344
- const marker = fenceMatch[1][0];
345
- if (fence === void 0) fence = marker;
346
- else if (fence === marker) fence = void 0;
347
- }
348
- const heading = fence === void 0 ? /^##\s+(.+?)\s*$/.exec(line) : null;
349
- if (heading?.[1] !== void 0) {
350
- if (current) sections.push({ question: current.question, answer: current.answer.join("\n") });
351
- current = { question: heading[1], answer: [] };
352
- continue;
353
- }
354
- if (current) current.answer.push(line);
355
- else preamble.push(line);
356
- }
357
- if (current) sections.push({ question: current.question, answer: current.answer.join("\n") });
358
- return { preamble: preamble.join("\n").trim(), sections };
276
+ const lines = markdown.split("\n");
277
+ const preamble = [];
278
+ const sections = [];
279
+ let current;
280
+ let fence;
281
+ for (const line of lines) {
282
+ const fenceMatch = /^\s{0,3}(`{3,}|~{3,})/.exec(line);
283
+ if (fenceMatch?.[1] !== void 0) {
284
+ const marker = fenceMatch[1][0];
285
+ if (fence === void 0) fence = marker;
286
+ else if (fence === marker) fence = void 0;
287
+ }
288
+ const heading = fence === void 0 ? /^##\s+(.+?)\s*$/.exec(line) : null;
289
+ if (heading?.[1] !== void 0) {
290
+ if (current) sections.push({
291
+ question: current.question,
292
+ answer: current.answer.join("\n")
293
+ });
294
+ current = {
295
+ question: heading[1],
296
+ answer: []
297
+ };
298
+ continue;
299
+ }
300
+ if (current) current.answer.push(line);
301
+ else preamble.push(line);
302
+ }
303
+ if (current) sections.push({
304
+ question: current.question,
305
+ answer: current.answer.join("\n")
306
+ });
307
+ return {
308
+ preamble: preamble.join("\n").trim(),
309
+ sections
310
+ };
359
311
  }
360
312
  function DocFaq({ children, className }) {
361
- const { preamble, sections } = splitFaq(children);
362
- const slugs = useMemo(() => sections.map((s) => docSlug(s.question)), [sections]);
363
- const [open, setOpen] = useState([]);
364
- useEffect(() => {
365
- if (typeof window === "undefined") return;
366
- const sync = () => {
367
- const id = readDocHash();
368
- if (id === "") return;
369
- const i = slugs.indexOf(id);
370
- if (i === -1) return;
371
- setOpen((prev) => prev.includes(`q${i}`) ? prev : [...prev, `q${i}`]);
372
- scrollToDocAnchor(id, document.body);
373
- };
374
- sync();
375
- window.addEventListener("hashchange", sync);
376
- return () => window.removeEventListener("hashchange", sync);
377
- }, [slugs]);
378
- if (sections.length === 0) return /* @__PURE__ */ jsx(DocMarkdown, { className, children });
379
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), "data-testid": "doc-faq", children: [
380
- preamble !== "" && /* @__PURE__ */ jsx(DocMarkdown, { className: "mb-2", children: preamble }),
381
- /* @__PURE__ */ jsx(Accordion, { type: "multiple", value: open, onValueChange: setOpen, className: "w-full", children: sections.map((s, i) => /* @__PURE__ */ jsxs(
382
- AccordionItem,
383
- {
384
- value: `q${i}`,
385
- id: slugs[i],
386
- className: "group/anchor scroll-mt-4",
387
- "data-testid": `doc-faq:item:${i}`,
388
- children: [
389
- /* @__PURE__ */ jsxs(AccordionTrigger, { children: [
390
- /* @__PURE__ */ jsx("span", { className: "min-w-0", children: s.question }),
391
- /* @__PURE__ */ jsx(DocAnchorLink, { slug: slugs[i], stopPropagation: true, className: "ml-auto mr-1" })
392
- ] }),
393
- /* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsx(DocMarkdown, { className: "prose-p:my-2 first:prose-p:mt-0 last:prose-p:mb-0", children: s.answer }) })
394
- ]
395
- },
396
- `${i}-${s.question}`
397
- )) })
398
- ] });
313
+ const { preamble, sections } = splitFaq(children);
314
+ const slugs = useMemo(() => sections.map((s) => docSlug(s.question)), [sections]);
315
+ const [open, setOpen] = useState([]);
316
+ useEffect(() => {
317
+ if (typeof window === "undefined") return;
318
+ const sync = () => {
319
+ const id = readDocHash();
320
+ if (id === "") return;
321
+ const i = slugs.indexOf(id);
322
+ if (i === -1) return;
323
+ setOpen((prev) => prev.includes(`q${i}`) ? prev : [...prev, `q${i}`]);
324
+ scrollToDocAnchor(id, document.body);
325
+ };
326
+ sync();
327
+ window.addEventListener("hashchange", sync);
328
+ return () => window.removeEventListener("hashchange", sync);
329
+ }, [slugs]);
330
+ if (sections.length === 0) return jsx(DocMarkdown, {
331
+ className,
332
+ children
333
+ });
334
+ return jsxs("div", {
335
+ className: cn("flex flex-col", className),
336
+ "data-testid": "doc-faq",
337
+ children: [preamble !== "" && jsx(DocMarkdown, {
338
+ className: "mb-2",
339
+ children: preamble
340
+ }), jsx(Accordion, {
341
+ type: "multiple",
342
+ value: open,
343
+ onValueChange: setOpen,
344
+ className: "w-full",
345
+ children: sections.map((s, i) => jsxs(AccordionItem, {
346
+ value: `q${i}`,
347
+ id: slugs[i],
348
+ className: "group/anchor scroll-mt-4",
349
+ "data-testid": `doc-faq:item:${i}`,
350
+ children: [jsxs(AccordionTrigger, { children: [jsx("span", {
351
+ className: "min-w-0",
352
+ children: s.question
353
+ }), jsx(DocAnchorLink, {
354
+ slug: slugs[i],
355
+ stopPropagation: true,
356
+ className: "ml-auto mr-1"
357
+ })] }), jsx(AccordionContent, { children: jsx(DocMarkdown, {
358
+ className: "prose-p:my-2 first:prose-p:mt-0 last:prose-p:mb-0",
359
+ children: s.answer
360
+ }) })]
361
+ }, `${i}-${s.question}`))
362
+ })]
363
+ });
399
364
  }
365
+ //#endregion
366
+ //#region src/markdown/index.tsx
400
367
  function DocMarkdown({ children, className }) {
401
- return /* @__PURE__ */ jsx(
402
- "div",
403
- {
404
- className: cn(
405
- "prose prose-sm max-w-none dark:prose-invert",
406
- // The default prose measure is wider than any panel we render into,
407
- // and its heading rhythm is tuned for a page rather than a column.
408
- "prose-headings:scroll-mt-4 prose-headings:font-semibold",
409
- "prose-h1:text-base prose-h2:text-[0.9375rem] prose-h3:text-sm",
410
- "prose-p:leading-[1.65]",
411
- "prose-a:font-medium prose-a:underline-offset-2",
412
- "prose-img:rounded-md prose-img:border",
413
- "prose-video:rounded-md prose-video:border prose-video:w-full",
414
- "prose-table:text-[0.8125rem]",
415
- className
416
- ),
417
- children: /* @__PURE__ */ jsx(
418
- Markdown,
419
- {
420
- remarkPlugins: [remarkGfm, remarkDirective, remarkVideoDirective],
421
- rehypePlugins: [rehypeSlug, [rehypeSanitize, docSanitizeSchema]],
422
- components: {
423
- // Every link in a body leaves the app; routing is not involved, so
424
- // this stays a plain anchor and the package stays router-agnostic.
425
- a: ({ href, children: kids, ...rest }) => /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", ...rest, children: kids }),
426
- // Long articles should not fetch every illustration up front. The
427
- // attribute has to be allow-listed in the schema too — it is in
428
- // neither `img` nor the `*` bucket by default.
429
- img: ({ ...rest }) => /* @__PURE__ */ jsx("img", { loading: "lazy", ...rest, alt: rest.alt ?? "" }),
430
- // A wide GFM table must scroll inside its own box rather than push
431
- // the panel — or the page — sideways.
432
- table: ({ children: kids, ...rest }) => /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsx("table", { ...rest, children: kids }) }),
433
- /*
434
- ```mermaid blocks become diagrams; every other fence stays a code
435
- block. `language-*` on `code` is already allow-listed by
436
- rehype-sanitize's default schema, so no schema change is owed —
437
- and the diagram source reaches MermaidDiagram as TEXT, never as
438
- markup, which is what keeps the sanitized pipeline sanitized.
439
- */
440
- code: ({ className: cls, children: kids, ...rest }) => {
441
- if (/\blanguage-mermaid\b/.test(cls ?? "")) {
442
- return /* @__PURE__ */ jsx(MermaidDiagram, { code: String(kids).replace(/\n$/, "") });
443
- }
444
- return /* @__PURE__ */ jsx("code", { className: cls, ...rest, children: kids });
445
- },
446
- /*
447
- A heading is a linkable place, and an anchor nobody can see is an
448
- anchor nobody uses — so each one carries a « # » that appears on
449
- hover or focus and puts the fragment in the address bar.
450
-
451
- The id on the element is `user-content-<slug>` (the sanitizer's
452
- clobber prefix); the href is the BARE slug, because that is what a
453
- person pastes and what `findDocAnchor` resolves. Keeping the visible
454
- link clean is the whole reason those two are allowed to differ.
455
- */
456
- h2: ({ children: kids, id, ...rest }) => /* @__PURE__ */ jsx(HeadingWithAnchor, { level: 2, id, ...rest, children: kids }),
457
- h3: ({ children: kids, id, ...rest }) => /* @__PURE__ */ jsx(HeadingWithAnchor, { level: 3, id, ...rest, children: kids }),
458
- /*
459
- A mermaid diagram replaces the whole block, so the <pre> that
460
- react-markdown wraps it in would contribute a stray bordered box
461
- around the figure.
462
- */
463
- pre: ({ children: kids, ...rest }) => {
464
- const only = Array.isArray(kids) ? kids[0] : kids;
465
- const cls = typeof only === "object" && only !== null && "props" in only ? only.props?.className ?? "" : "";
466
- if (/\blanguage-mermaid\b/.test(cls)) return /* @__PURE__ */ jsx(Fragment, { children: kids });
467
- return /* @__PURE__ */ jsx("pre", { ...rest, children: kids });
468
- }
469
- },
470
- children
471
- }
472
- )
473
- }
474
- );
368
+ return jsx("div", {
369
+ className: cn("prose prose-sm max-w-none dark:prose-invert", "prose-headings:scroll-mt-4 prose-headings:font-semibold", "prose-h1:text-base prose-h2:text-[0.9375rem] prose-h3:text-sm", "prose-p:leading-[1.65]", "prose-a:font-medium prose-a:underline-offset-2", "prose-img:rounded-md prose-img:border", "prose-video:rounded-md prose-video:border prose-video:w-full", "prose-table:text-[0.8125rem]", className),
370
+ children: jsx(Markdown, {
371
+ remarkPlugins: [
372
+ remarkGfm,
373
+ remarkDirective,
374
+ remarkVideoDirective
375
+ ],
376
+ rehypePlugins: [rehypeSlug, [rehypeSanitize, docSanitizeSchema]],
377
+ components: {
378
+ a: ({ href, children: kids, ...rest }) => jsx("a", {
379
+ href,
380
+ target: "_blank",
381
+ rel: "noopener noreferrer",
382
+ ...rest,
383
+ children: kids
384
+ }),
385
+ img: ({ ...rest }) => jsx("img", {
386
+ loading: "lazy",
387
+ ...rest,
388
+ alt: rest.alt ?? ""
389
+ }),
390
+ table: ({ children: kids, ...rest }) => jsx("div", {
391
+ className: "overflow-x-auto",
392
+ children: jsx("table", {
393
+ ...rest,
394
+ children: kids
395
+ })
396
+ }),
397
+ code: ({ className: cls, children: kids, ...rest }) => {
398
+ if (/\blanguage-mermaid\b/.test(cls ?? "")) return jsx(MermaidDiagram, { code: String(kids).replace(/\n$/, "") });
399
+ return jsx("code", {
400
+ className: cls,
401
+ ...rest,
402
+ children: kids
403
+ });
404
+ },
405
+ h2: ({ children: kids, id, ...rest }) => jsx(HeadingWithAnchor, {
406
+ level: 2,
407
+ id,
408
+ ...rest,
409
+ children: kids
410
+ }),
411
+ h3: ({ children: kids, id, ...rest }) => jsx(HeadingWithAnchor, {
412
+ level: 3,
413
+ id,
414
+ ...rest,
415
+ children: kids
416
+ }),
417
+ pre: ({ children: kids, ...rest }) => {
418
+ const only = Array.isArray(kids) ? kids[0] : kids;
419
+ const cls = typeof only === "object" && only !== null && "props" in only ? only.props?.className ?? "" : "";
420
+ if (/\blanguage-mermaid\b/.test(cls)) return jsx(Fragment$1, { children: kids });
421
+ return jsx("pre", {
422
+ ...rest,
423
+ children: kids
424
+ });
425
+ }
426
+ },
427
+ children
428
+ })
429
+ });
475
430
  }
476
- function HeadingWithAnchor({
477
- level,
478
- id,
479
- children,
480
- ...rest
481
- }) {
482
- const Tag = level === 2 ? "h2" : "h3";
483
- const slug = id?.startsWith(DOC_ID_PREFIX) ? id.slice(DOC_ID_PREFIX.length) : id;
484
- return /* @__PURE__ */ jsxs(Tag, { id, className: "group/anchor scroll-mt-4", ...rest, children: [
485
- children,
486
- slug !== void 0 && slug !== "" && /* @__PURE__ */ jsx(DocAnchorLink, { slug })
487
- ] });
431
+ function HeadingWithAnchor({ level, id, children, ...rest }) {
432
+ const Tag = level === 2 ? "h2" : "h3";
433
+ const slug = id?.startsWith("user-content-") ? id.slice(DOC_ID_PREFIX.length) : id;
434
+ return jsxs(Tag, {
435
+ id,
436
+ className: "group/anchor scroll-mt-4",
437
+ ...rest,
438
+ children: [children, slug !== void 0 && slug !== "" && jsx(DocAnchorLink, { slug })]
439
+ });
488
440
  }
441
+ //#endregion
442
+ export { DOC_ID_PREFIX, DocAnchorLink, DocFaq, DocMarkdown, MermaidDiagram, docSanitizeSchema, docShareUrl, docSlug, findDocAnchor, readDocHash, remarkVideoDirective, scrollToDocAnchor, splitFaq };
489
443
 
490
- export { DocAnchorLink, DocFaq, DocMarkdown, MermaidDiagram, docSanitizeSchema, remarkVideoDirective, splitFaq };
491
- //# sourceMappingURL=index.js.map
492
444
  //# sourceMappingURL=index.js.map