@ngrok/mantle 0.68.2 → 0.68.4

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.
@@ -149,7 +149,7 @@ declare const AlertDialog: {
149
149
  readonly Action: _$react.ForwardRefExoticComponent<(Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
150
150
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
151
151
  isLoading?: boolean | null | undefined;
152
- priority?: "default" | "danger" | "neutral" | null | undefined;
152
+ priority?: "danger" | "neutral" | "default" | null | undefined;
153
153
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
154
154
  icon?: ReactNode;
155
155
  iconPlacement?: "start" | "end";
@@ -159,7 +159,7 @@ declare const AlertDialog: {
159
159
  }, "ref"> | Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
160
160
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
161
161
  isLoading?: boolean | null | undefined;
162
- priority?: "default" | "danger" | "neutral" | null | undefined;
162
+ priority?: "danger" | "neutral" | "default" | null | undefined;
163
163
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
164
164
  icon?: ReactNode;
165
165
  iconPlacement?: "start" | "end";
@@ -206,7 +206,7 @@ declare const AlertDialog: {
206
206
  readonly Cancel: _$react.ForwardRefExoticComponent<(Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
207
207
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
208
208
  isLoading?: boolean | null | undefined;
209
- priority?: "default" | "danger" | "neutral" | null | undefined;
209
+ priority?: "danger" | "neutral" | "default" | null | undefined;
210
210
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
211
211
  icon?: ReactNode;
212
212
  iconPlacement?: "start" | "end";
@@ -216,7 +216,7 @@ declare const AlertDialog: {
216
216
  }, "ref"> | Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
217
217
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
218
218
  isLoading?: boolean | null | undefined;
219
- priority?: "default" | "danger" | "neutral" | null | undefined;
219
+ priority?: "danger" | "neutral" | "default" | null | undefined;
220
220
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
221
221
  icon?: ReactNode;
222
222
  iconPlacement?: "start" | "end";
@@ -9,7 +9,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
9
9
  declare const buttonVariants: (props?: ({
10
10
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
11
11
  isLoading?: boolean | null | undefined;
12
- priority?: "default" | "danger" | "neutral" | null | undefined;
12
+ priority?: "danger" | "neutral" | "default" | null | undefined;
13
13
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
14
14
  type ButtonVariants = VariantProps$1<typeof buttonVariants>;
15
15
  /**
@@ -93,7 +93,7 @@ type ButtonProps = ComponentProps<"button"> & ButtonVariants & {
93
93
  declare const Button: _$react.ForwardRefExoticComponent<(Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
94
94
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
95
95
  isLoading?: boolean | null | undefined;
96
- priority?: "default" | "danger" | "neutral" | null | undefined;
96
+ priority?: "danger" | "neutral" | "default" | null | undefined;
97
97
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
98
98
  /**
99
99
  * An icon to render inside the button. If the `state` is `"pending"`, then
@@ -139,7 +139,7 @@ declare const Button: _$react.ForwardRefExoticComponent<(Omit<_$react.ClassAttri
139
139
  }, "ref"> | Omit<_$react.ClassAttributes<HTMLButtonElement> & _$react.ButtonHTMLAttributes<HTMLButtonElement> & Partial<DeepNonNullable<_$class_variance_authority0.VariantProps<(props?: ({
140
140
  appearance?: "filled" | "link" | "ghost" | "outlined" | null | undefined;
141
141
  isLoading?: boolean | null | undefined;
142
- priority?: "default" | "danger" | "neutral" | null | undefined;
142
+ priority?: "danger" | "neutral" | "default" | null | undefined;
143
143
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string>>> & {
144
144
  /**
145
145
  * An icon to render inside the button. If the `state` is `"pending"`, then
@@ -172,4 +172,4 @@ declare const Button: _$react.ForwardRefExoticComponent<(Omit<_$react.ClassAttri
172
172
  }, "ref">) & _$react.RefAttributes<HTMLButtonElement>>;
173
173
  //#endregion
174
174
  export { ButtonProps as n, Button as t };
175
- //# sourceMappingURL=button-BaNwe1ud.d.ts.map
175
+ //# sourceMappingURL=button-CX98GGHD.d.ts.map
package/dist/button.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { n as IconButtonProps, t as IconButton } from "./icon-button-gO-7F_MZ.js";
2
- import { n as ButtonProps, t as Button } from "./button-BaNwe1ud.js";
3
- import { n as ButtonGroupProps, t as ButtonGroup } from "./index-BCZ3y0yi.js";
2
+ import { n as ButtonProps, t as Button } from "./button-CX98GGHD.js";
3
+ import { n as ButtonGroupProps, t as ButtonGroup } from "./index-Cj2NX2Dg.js";
4
4
  export { Button, ButtonGroup, ButtonGroupProps, ButtonProps, IconButton, IconButtonProps };
@@ -19,7 +19,7 @@ type CheckedState = boolean | "indeterminate";
19
19
  * </form>
20
20
  * ```
21
21
  */
22
- declare const Checkbox: _$react.ForwardRefExoticComponent<Omit<Omit<_$react.DetailedHTMLProps<_$react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultChecked" | "type" | "checked"> & WithValidation & {
22
+ declare const Checkbox: _$react.ForwardRefExoticComponent<Omit<Omit<_$react.DetailedHTMLProps<_$react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultChecked" | "checked" | "type"> & WithValidation & {
23
23
  /**
24
24
  * The controlled checked state of the checkbox. Must be used in conjunction with onChange.
25
25
  */
@@ -1,114 +1,11 @@
1
1
  import { t as SvgAttributes } from "./types-yU-Byhue.js";
2
2
  import { t as WithAsChild } from "./as-child-CRRsxi3Y.js";
3
- import { C as parseLanguage, D as LineRange, E as decorateHighlightedHtml, S as isSupportedLanguage, _ as normalizeIndentation, a as Mode, b as isIndentation, c as ResolvedPreRenderedCodeBlockProps, d as parseMetastring, f as resolvePreRenderedCodeBlockProps, g as parseCodeBlockShowLineNumbers, h as parseCodeBlockLineNumberStart, i as MetaInput, l as defaultMeta, m as parseCodeBlockHighlightLines, n as DefaultMeta, o as ResolvePreRenderedCodeBlockPropsInput, p as tokenizeMetastring, r as Meta, s as ResolvePreRenderedCodeBlockPropsResult, t as CodeBlockPreElementInput, u as normalizeValue, v as Indentation, w as supportedLanguages, x as SupportedLanguage, y as inferIndentation } from "./resolve-pre-rendered-props-51i50IL2.js";
3
+ import { C as Indentation, D as isSupportedLanguage, E as SupportedLanguage, M as LineRange, O as parseLanguage, S as normalizeIndentation, T as isIndentation, _ as MantleCodeBlockValue, a as Mode, c as ResolvedPreRenderedCodeBlockProps, d as parseMetastring, f as resolvePreRenderedCodeBlockProps, g as parseCodeBlockShowLineNumbers, h as parseCodeBlockLineNumberStart, i as MetaInput, j as decorateHighlightedHtml, k as supportedLanguages, l as defaultMeta, m as parseCodeBlockHighlightLines, n as DefaultMeta, o as ResolvePreRenderedCodeBlockPropsInput, p as tokenizeMetastring, r as Meta, s as ResolvePreRenderedCodeBlockPropsResult, t as CodeBlockPreElementInput, u as normalizeValue, v as MantleCodeOptions, w as inferIndentation, x as mantleCode, y as createMantleCodeBlockValue } from "./resolve-pre-rendered-props-B3YDbOFZ.js";
4
4
  import * as _$react from "react";
5
5
  import { ComponentProps, HTMLAttributes, ReactNode } from "react";
6
6
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
7
7
  import { Content, List, Trigger } from "@radix-ui/react-tabs";
8
8
 
9
- //#region src/components/code-block/mantle-code.d.ts
10
- declare const mantleCodeBlockValueBrand: unique symbol;
11
- /**
12
- * The value produced by `mantleCode()`. Contains pre-rendered Shiki HTML (injected
13
- * by the Vite plugin at build time) and the original code string for the copy button.
14
- *
15
- * `~preHtml` is required at render time. Runtime syntax highlighting is intentionally
16
- * unsupported; only placeholder substitution for interpolated values is performed.
17
- */
18
- type MantleCodeBlockValue = {
19
- /**
20
- * Nominal type brand to prevent accidental use of plain objects.
21
- */
22
- [mantleCodeBlockValueBrand]: true;
23
- /**
24
- * The language used for syntax highlighting.
25
- */
26
- language: SupportedLanguage;
27
- /**
28
- * The original code string (used by the copy button).
29
- */
30
- code: string;
31
- /**
32
- * Fully pre-rendered Shiki HTML injected by the Vite plugin or server highlighter.
33
- * This must be present for rendering.
34
- *
35
- * **Security:** This HTML is injected via `dangerouslySetInnerHTML`. It must
36
- * come from a trusted source (Shiki output from the Vite plugin or
37
- * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input.
38
- */
39
- "~preHtml"?: string | undefined;
40
- /**
41
- * Runtime values used to replace `SHIKI_VAL_N` placeholders in `~preHtml`.
42
- * This enables interpolated template expressions while preserving build-time highlighting.
43
- */
44
- "~preVals"?: unknown[] | undefined;
45
- /**
46
- * Placeholder token prefix used by the Vite transform for interpolated values.
47
- * When omitted, CodeBlock falls back to the legacy `SHIKI_VAL_<n>` format.
48
- */
49
- "~preValToken"?: string | undefined;
50
- /**
51
- * Optional default for line-number rendering when this value is displayed.
52
- */
53
- "~showLineNumbers"?: boolean | undefined;
54
- /**
55
- * Optional default highlighted line numbers/ranges when this value is displayed.
56
- */
57
- "~highlightLines"?: (LineRange | number)[] | undefined;
58
- /**
59
- * Optional default start line number when line numbers are displayed.
60
- * @default 1
61
- */
62
- "~lineNumberStart"?: number | undefined;
63
- };
64
- /** Maps each key starting with `OldPrefix` to `NewPrefix`, leaving other keys unchanged. */
65
- type ReplacePrefix<T, OldPrefix extends string, NewPrefix extends string> = { [K in keyof T as K extends `${OldPrefix}${infer Rest}` ? `${NewPrefix}${Rest}` : K]: T[K] };
66
- /** Public input shape for `createMantleCodeBlockValue`, with `~`-prefixed keys renamed to unprefixed. */
67
- type MantleCodeBlockValueInput = ReplacePrefix<Omit<MantleCodeBlockValue, typeof mantleCodeBlockValueBrand>, "~", "">;
68
- /** Options for configuring line numbers, highlights, and indentation in `mantleCode()`. */
69
- type MantleCodeOptions = {
70
- highlightLines?: (LineRange | number)[] | undefined;
71
- indentation?: Indentation | undefined;
72
- lineNumberStart?: number | undefined;
73
- showLineNumbers?: boolean | undefined;
74
- };
75
- /**
76
- * Creates a `MantleCodeBlockValue` for use with `CodeBlock.Code`.
77
- *
78
- * **Security:** The `preHtml` field is rendered via `dangerouslySetInnerHTML`.
79
- * Only pass HTML produced by Shiki (via the Vite plugin or
80
- * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input as `preHtml`.
81
- */
82
- declare function createMantleCodeBlockValue({
83
- preHtml,
84
- preValToken,
85
- preVals,
86
- highlightLines,
87
- lineNumberStart,
88
- showLineNumbers,
89
- code,
90
- language
91
- }: MantleCodeBlockValueInput): MantleCodeBlockValue;
92
- /**
93
- * Tagged template literal for Shiki syntax highlighting.
94
- *
95
- * Returns a `MantleCodeBlockValue` that `CodeBlock.Code` renders.
96
- * The Vite transform plugin rewrites calls to this function at build time,
97
- * inlining pre-rendered Shiki HTML so that no highlighting work happens in the browser.
98
- * Configure it via `mantleCodeBlockPlugins()` in `vite.config.ts`.
99
- *
100
- * Interpolated template expressions are supported via placeholder substitution.
101
- *
102
- * @example
103
- * ```tsx
104
- * // Static string
105
- * mantleCode("typescript")`const x: string = "hello";`
106
- * // Interpolated string
107
- * mantleCode("typescript")`const greeting = "Hello, ${name}!";`
108
- * ```
109
- */
110
- declare function mantleCode(language: SupportedLanguage, options?: MantleCodeOptions): (strings: TemplateStringsArray, ...values: unknown[]) => MantleCodeBlockValue;
111
- //#endregion
112
9
  //#region src/components/code-block/code-block.d.ts
113
10
  type CodeBlockRootProps = Omit<ComponentProps<"div">, "align"> & WithAsChild & {
114
11
  /**
@@ -1,3 +1,3 @@
1
- import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-BMH0fD_b.js";import{t as n}from"./slot-D_ZUrdEW.js";import{t as r}from"./icon-button-CxxVPiKp.js";import{t as i}from"./use-copy-to-clipboard-B6wH6hDd.js";import{t as a}from"./traffic-policy-file-CroUMbsd.js";import{a as o,c as s,d as c,f as l,h as u,i as d,l as f,m as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b}from"./resolve-pre-rendered-props-Bu2cvS9A.js";import{CaretDownIcon as x}from"@phosphor-icons/react/CaretDown";import{createContext as S,forwardRef as C,useCallback as w,useContext as T,useEffect as E,useId as ee,useLayoutEffect as te,useMemo as D,useRef as O,useState as k}from"react";import A from"tiny-invariant";import{jsx as j,jsxs as ne}from"react/jsx-runtime";import{CheckIcon as re}from"@phosphor-icons/react/Check";import{CopyIcon as ie}from"@phosphor-icons/react/Copy";import{FileTextIcon as M}from"@phosphor-icons/react/FileText";import{TerminalIcon as ae}from"@phosphor-icons/react/Terminal";import{Content as oe,List as se,Root as N,Trigger as ce}from"@radix-ui/react-tabs";function P(e){let t=-1;for(let n=0;n<e.length;n++){let r=e[n];if(r===`&`||r===`<`||r===`>`||r===`"`||r===`'`){t=n;break}}if(t===-1)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e[r];switch(t){case`&`:n+=`&amp;`;break;case`<`:n+=`&lt;`;break;case`>`:n+=`&gt;`;break;case`"`:n+=`&quot;`;break;case`'`:n+=`&#39;`;break;default:n+=t}}return n}const F=S(null);function I(){let e=T(F);return A(e!=null,`CodeBlock subcomponents must be rendered within a <CodeBlock.Root>.`),e}const L=C(({asChild:t=!1,className:r,defaultTab:i,activeTab:a,onActiveTabChange:o,...s},c)=>{let l=O(``),[u,d]=k(!1),[f,p]=k(!1),[m,h]=k(void 0),g=w(e=>{h(t=>(A(t==null,`You can only render a single CodeBlock.Code within a CodeBlock.`),e))},[]),_=w(e=>{h(t=>{A(t===e,`You can only render a single CodeBlock.Code within a CodeBlock.`)})},[]),v=D(()=>({codeId:m,copyTextRef:l,hasCodeExpander:u,isCodeExpanded:f,registerCodeId:g,setHasCodeExpander:d,setIsCodeExpanded:p,unregisterCodeId:_}),[m,u,f,g,_]),y=i!==void 0||a!==void 0,b=j(t?n:`div`,{"data-slot":`code-block`,className:e(`text-mono w-full overflow-hidden rounded-md border border-gray-300 bg-card font-mono`,`[&_svg]:shrink-0`,r),ref:c,...s});return j(F.Provider,{value:v,children:y?j(N,{asChild:!0,defaultValue:i,value:a,onValueChange:o,children:b}):b})});L.displayName=`CodeBlock`;const R=C(({asChild:t=!1,className:r,...i},a)=>j(t?n:`div`,{className:e(`relative`,r),ref:a,...i}));R.displayName=`CodeBlockBody`;const le=/SHIKI_VAL_(\d+)/g;function ue(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const z=new Map;function B(e){if(e==null||e.length===0)return le;let t=z.get(e);return t??(z.size>=500&&z.clear(),t=RegExp(`${ue(e)}(\\d+)__`,`g`),z.set(e,t)),t}function V(e,t,n,r){if(n==null){if(!e.includes(`SHIKI_VAL_`))return e}else if(!e.includes(n))return e;return e.replaceAll(B(n),(e,n)=>{let i=Number.parseInt(n,10);return Number.isNaN(i)||i<0||i>=t.length?e:r(t[i])})}function H(e,t,n){return V(e,t,n,e=>P(String(e)))}function de(e,t,n){return V(e,t,n,e=>String(e))}const U=C(({className:t,style:n,tabIndex:r,value:i,...a},o)=>{let s=ee(),{copyTextRef:c,hasCodeExpander:l,isCodeExpanded:u,registerCodeId:d,unregisterCodeId:f}=I(),{language:p,code:m,"~preValToken":h,"~preVals":g,"~highlightLines":_,"~lineNumberStart":v,"~preHtml":y,"~showLineNumbers":b}=i,x=_,S=v??1,C=b??!1,w=D(()=>g!=null&&g.length>0?de(m,g,h):m,[h,g,m]);te(()=>{c.current=w},[c,w]),E(()=>(d(s),()=>{f(s)}),[s,d,f]);let T=D(()=>{if(y!=null)return g!=null&&g.length>0?H(y,g,h):y},[y,h,g]),O=T!=null,k=T??P(w);return j(`pre`,{"aria-expanded":l?u:void 0,className:e(`scrollbar overflow-x-auto overflow-y-hidden py-4`,!O&&`pr-14`,`data-[mantle-line-numbers~='false']:pl-4`,`text-mono m-0 font-mono`,`aria-collapsed:max-h-[13.6rem]`,t),"data-highlighted":O?`true`:`false`,"data-lang":p,"data-mantle-highlight-lines":O&&x!=null&&x.length>0?x.join(`,`):void 0,"data-mantle-line-number-start":O&&C?String(S):`1`,"data-mantle-line-numbers":O&&C?`true`:`false`,id:s,ref:o,style:{...n,"--mantle-line-number-start":String(S),tabSize:2,MozTabSize:2},tabIndex:r??-1,...a,children:j(`code`,{className:`text-size-inherit block min-w-full w-max`,dangerouslySetInnerHTML:{__html:k}})})});U.displayName=`CodeBlockCode`;const W=C(({asChild:t=!1,className:r,...i},a)=>j(t?n:`div`,{className:e(`flex items-center gap-1 border-b border-gray-300 bg-base px-4 py-2 text-gray-700`,r),ref:a,...i}));W.displayName=`CodeBlockHeader`;const G=C(({asChild:t=!1,className:r,...i},a)=>j(t?n:`h3`,{ref:a,className:e(`text-mono m-0 font-mono font-normal`,r),...i}));G.displayName=`CodeBlockTitle`;const K=C(({className:e,onCopy:t,onCopyError:n,onClick:a,...o},s)=>{let{copyTextRef:c}=I(),[,l]=i(),[u,d]=k(!1),f=O(void 0);return E(()=>()=>{f.current!=null&&clearTimeout(f.current)},[]),j(`span`,{className:`absolute right-2.5 top-2.5 z-10 bg-card`,children:j(r,{type:`button`,appearance:`ghost`,size:`sm`,label:`Copy code`,icon:j(u?re:ie,{}),className:e,ref:s,onClick:async e=>{try{if(a?.(e),e.defaultPrevented){f.current!=null&&clearTimeout(f.current);return}let n=c.current;await l(n),t?.(n),d(!0),f.current!=null&&clearTimeout(f.current),f.current=setTimeout(()=>{d(!1)},2e3)}catch(e){n?.(e)}},...o})})});K.displayName=`CodeBlockCopyButton`;const q=C(({asChild:r=!1,className:i,onClick:a,...o},s)=>{let{codeId:c,isCodeExpanded:l,setIsCodeExpanded:u,setHasCodeExpander:d}=I();return E(()=>(d(!0),()=>{d(!1)}),[d]),ne(r?n:`button`,{...o,"aria-controls":c,"aria-expanded":l,className:e(`flex w-full items-center justify-center gap-0.5 border-t border-gray-300 bg-card px-4 py-2 font-sans text-gray-700 hover:bg-gray-100`,i),ref:s,type:`button`,onClick:e=>{u(e=>!e),a?.(e)},children:[l?`Show less`:`Show more`,` `,j(t,{svg:j(x,{weight:`bold`}),className:e(`size-4`,l&&`rotate-180`,`transition-all duration-150`)})]})});q.displayName=`CodeBlockExpanderButton`;function J({className:e,preset:n,svg:r,...i}){let o=r;if(n!=null)switch(n){case`file`:o=j(M,{weight:`fill`});break;case`cli`:o=j(ae,{weight:`fill`});break;case`traffic-policy`:o=j(a,{});break}return j(t,{className:e,svg:o,...i})}J.displayName=`CodeBlockIcon`;const Y=C(({className:t,...n},r)=>j(se,{className:e(`flex items-center gap-1`,t),ref:r,...n}));Y.displayName=`CodeBlockTabList`;const X=C(({className:t,...n},r)=>j(ce,{className:e(`cursor-pointer rounded px-1.5 py-0.5 text-xs font-medium`,`text-gray-600 outline-hidden`,`hover:text-gray-900`,`data-[state=active]:bg-neutral-500/15 data-[state=active]:text-strong`,`focus-visible:ring-focus-accent focus-visible:ring-4`,t),ref:r,...n}));X.displayName=`CodeBlockTabTrigger`;const Z=C((e,t)=>j(oe,{ref:t,...e}));Z.displayName=`CodeBlockTabContent`;const Q={Root:L,Body:R,Code:U,CopyButton:K,ExpanderButton:q,Header:W,Icon:J,TabContent:Z,TabList:Y,TabTrigger:X,Title:G},fe=Symbol(`MantleCodeBlockValue`);function $({preHtml:e,preValToken:t,preVals:n,highlightLines:r,lineNumberStart:i,showLineNumbers:a,code:o,language:s}){return{[fe]:!0,language:s,code:o,"~preHtml":e,"~preValToken":t,"~preVals":n,"~highlightLines":r,"~lineNumberStart":i,"~showLineNumbers":a}}function pe(e,t){let n=``;for(let r=0;r<e.length;r+=1)n+=e[r]??``,r<t.length&&(n+=String(t[r]));return n}function me(e,t={}){return(n,...r)=>$({language:e,code:pe(n,r),preHtml:void 0,preVals:r.length>0?r:void 0,highlightLines:t.highlightLines,lineNumberStart:t.lineNumberStart,showLineNumbers:t.showLineNumbers})}function he(e,t){let n=1;if(n>t)return!0;for(let r=0;r<e.length;r++)if(e[r]===`
2
- `&&(n+=1,n>t))return!0;return!1}export{Q as CodeBlock,$ as createMantleCodeBlockValue,u as decorateHighlightedHtml,y as defaultMeta,P as escapeHtml,he as hasMoreThanNLines,g as inferIndentation,p as isIndentation,f as isSupportedLanguage,me as mantleCode,l as normalizeIndentation,m as normalizeValue,h as parseCodeBlockHighlightLines,v as parseCodeBlockLineNumberStart,s as parseCodeBlockShowLineNumbers,b as parseLanguage,_ as parseMetastring,d as resolvePreRenderedCodeBlockProps,c as supportedLanguages,o as tokenizeMetastring};
1
+ import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-BMH0fD_b.js";import{t as n}from"./slot-D_ZUrdEW.js";import{t as r}from"./icon-button-CxxVPiKp.js";import{t as i}from"./use-copy-to-clipboard-B6wH6hDd.js";import{t as a}from"./traffic-policy-file-CroUMbsd.js";import{a as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x,v as S}from"./resolve-pre-rendered-props--3gLTSwE.js";import{CaretDownIcon as C}from"@phosphor-icons/react/CaretDown";import{createContext as w,forwardRef as T,useCallback as E,useContext as D,useEffect as O,useId as ee,useLayoutEffect as te,useMemo as k,useRef as A,useState as j}from"react";import M from"tiny-invariant";import{jsx as N,jsxs as P}from"react/jsx-runtime";import{CheckIcon as F}from"@phosphor-icons/react/Check";import{CopyIcon as I}from"@phosphor-icons/react/Copy";import{FileTextIcon as L}from"@phosphor-icons/react/FileText";import{TerminalIcon as ne}from"@phosphor-icons/react/Terminal";import{Content as re,List as ie,Root as ae,Trigger as oe}from"@radix-ui/react-tabs";function R(e){let t=-1;for(let n=0;n<e.length;n++){let r=e[n];if(r===`&`||r===`<`||r===`>`||r===`"`||r===`'`){t=n;break}}if(t===-1)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e[r];switch(t){case`&`:n+=`&amp;`;break;case`<`:n+=`&lt;`;break;case`>`:n+=`&gt;`;break;case`"`:n+=`&quot;`;break;case`'`:n+=`&#39;`;break;default:n+=t}}return n}const z=w(null);function B(){let e=D(z);return M(e!=null,`CodeBlock subcomponents must be rendered within a <CodeBlock.Root>.`),e}const V=T(({asChild:t=!1,className:r,defaultTab:i,activeTab:a,onActiveTabChange:o,...s},c)=>{let l=A(``),[u,d]=j(!1),[f,p]=j(!1),[m,h]=j(void 0),g=E(e=>{h(t=>(M(t==null,`You can only render a single CodeBlock.Code within a CodeBlock.`),e))},[]),_=E(e=>{h(t=>{M(t===e,`You can only render a single CodeBlock.Code within a CodeBlock.`)})},[]),v=k(()=>({codeId:m,copyTextRef:l,hasCodeExpander:u,isCodeExpanded:f,registerCodeId:g,setHasCodeExpander:d,setIsCodeExpanded:p,unregisterCodeId:_}),[m,u,f,g,_]),y=i!==void 0||a!==void 0,b=N(t?n:`div`,{"data-slot":`code-block`,className:e(`text-mono w-full overflow-hidden rounded-md border border-gray-300 bg-card font-mono`,`[&_svg]:shrink-0`,r),ref:c,...s});return N(z.Provider,{value:v,children:y?N(ae,{asChild:!0,defaultValue:i,value:a,onValueChange:o,children:b}):b})});V.displayName=`CodeBlock`;const H=T(({asChild:t=!1,className:r,...i},a)=>N(t?n:`div`,{className:e(`relative`,r),ref:a,...i}));H.displayName=`CodeBlockBody`;const se=/SHIKI_VAL_(\d+)/g;function ce(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const U=new Map;function le(e){if(e==null||e.length===0)return se;let t=U.get(e);return t??(U.size>=500&&U.clear(),t=RegExp(`${ce(e)}(\\d+)__`,`g`),U.set(e,t)),t}function W(e,t,n,r){if(n==null){if(!e.includes(`SHIKI_VAL_`))return e}else if(!e.includes(n))return e;return e.replaceAll(le(n),(e,n)=>{let i=Number.parseInt(n,10);return Number.isNaN(i)||i<0||i>=t.length?e:r(t[i])})}function ue(e,t,n){return W(e,t,n,e=>R(String(e)))}function de(e,t,n){return W(e,t,n,e=>String(e))}const G=T(({className:t,style:n,tabIndex:r,value:i,...a},o)=>{let s=ee(),{copyTextRef:c,hasCodeExpander:l,isCodeExpanded:u,registerCodeId:d,unregisterCodeId:f}=B(),{language:p,code:m,"~preValToken":h,"~preVals":g,"~highlightLines":_,"~lineNumberStart":v,"~preHtml":y,"~showLineNumbers":b}=i,x=_,S=v??1,C=b??!1,w=k(()=>g!=null&&g.length>0?de(m,g,h):m,[h,g,m]);te(()=>{c.current=w},[c,w]),O(()=>(d(s),()=>{f(s)}),[s,d,f]);let T=k(()=>{if(y!=null)return g!=null&&g.length>0?ue(y,g,h):y},[y,h,g]),E=T!=null,D=T??R(w);return N(`pre`,{"aria-expanded":l?u:void 0,className:e(`scrollbar overflow-x-auto overflow-y-hidden py-4`,!E&&`pr-14`,`data-[mantle-line-numbers~='false']:pl-4`,`text-mono m-0 font-mono`,`aria-collapsed:max-h-[13.6rem]`,t),"data-highlighted":E?`true`:`false`,"data-lang":p,"data-mantle-highlight-lines":E&&x!=null&&x.length>0?x.join(`,`):void 0,"data-mantle-line-number-start":E&&C?String(S):`1`,"data-mantle-line-numbers":E&&C?`true`:`false`,id:s,ref:o,style:{...n,"--mantle-line-number-start":String(S),tabSize:2,MozTabSize:2},tabIndex:r??-1,...a,children:N(`code`,{className:`text-size-inherit block min-w-full w-max`,dangerouslySetInnerHTML:{__html:D}})})});G.displayName=`CodeBlockCode`;const K=T(({asChild:t=!1,className:r,...i},a)=>N(t?n:`div`,{className:e(`flex items-center gap-1 border-b border-gray-300 bg-base px-4 py-2 text-gray-700`,r),ref:a,...i}));K.displayName=`CodeBlockHeader`;const q=T(({asChild:t=!1,className:r,...i},a)=>N(t?n:`h3`,{ref:a,className:e(`text-mono m-0 font-mono font-normal`,r),...i}));q.displayName=`CodeBlockTitle`;const J=T(({className:e,onCopy:t,onCopyError:n,onClick:a,...o},s)=>{let{copyTextRef:c}=B(),[,l]=i(),[u,d]=j(!1),f=A(void 0);return O(()=>()=>{f.current!=null&&clearTimeout(f.current)},[]),N(`span`,{className:`absolute right-2.5 top-2.5 z-10 bg-card`,children:N(r,{type:`button`,appearance:`ghost`,size:`sm`,label:`Copy code`,icon:N(u?F:I,{}),className:e,ref:s,onClick:async e=>{try{if(a?.(e),e.defaultPrevented){f.current!=null&&clearTimeout(f.current);return}let n=c.current;await l(n),t?.(n),d(!0),f.current!=null&&clearTimeout(f.current),f.current=setTimeout(()=>{d(!1)},2e3)}catch(e){n?.(e)}},...o})})});J.displayName=`CodeBlockCopyButton`;const Y=T(({asChild:r=!1,className:i,onClick:a,...o},s)=>{let{codeId:c,isCodeExpanded:l,setIsCodeExpanded:u,setHasCodeExpander:d}=B();return O(()=>(d(!0),()=>{d(!1)}),[d]),P(r?n:`button`,{...o,"aria-controls":c,"aria-expanded":l,className:e(`flex w-full items-center justify-center gap-0.5 border-t border-gray-300 bg-card px-4 py-2 font-sans text-gray-700 hover:bg-gray-100`,i),ref:s,type:`button`,onClick:e=>{u(e=>!e),a?.(e)},children:[l?`Show less`:`Show more`,` `,N(t,{svg:N(C,{weight:`bold`}),className:e(`size-4`,l&&`rotate-180`,`transition-all duration-150`)})]})});Y.displayName=`CodeBlockExpanderButton`;function X({className:e,preset:n,svg:r,...i}){let o=r;if(n!=null)switch(n){case`file`:o=N(L,{weight:`fill`});break;case`cli`:o=N(ne,{weight:`fill`});break;case`traffic-policy`:o=N(a,{});break}return N(t,{className:e,svg:o,...i})}X.displayName=`CodeBlockIcon`;const Z=T(({className:t,...n},r)=>N(ie,{className:e(`flex items-center gap-1`,t),ref:r,...n}));Z.displayName=`CodeBlockTabList`;const Q=T(({className:t,...n},r)=>N(oe,{className:e(`cursor-pointer rounded px-1.5 py-0.5 text-xs font-medium`,`text-gray-600 outline-hidden`,`hover:text-gray-900`,`data-[state=active]:bg-neutral-500/15 data-[state=active]:text-strong`,`focus-visible:ring-focus-accent focus-visible:ring-4`,t),ref:r,...n}));Q.displayName=`CodeBlockTabTrigger`;const $=T((e,t)=>N(re,{ref:t,...e}));$.displayName=`CodeBlockTabContent`;const fe={Root:V,Body:H,Code:G,CopyButton:J,ExpanderButton:Y,Header:K,Icon:X,TabContent:$,TabList:Z,TabTrigger:Q,Title:q};function pe(e,t){let n=1;if(n>t)return!0;for(let r=0;r<e.length;r++)if(e[r]===`
2
+ `&&(n+=1,n>t))return!0;return!1}export{fe as CodeBlock,u as createMantleCodeBlockValue,d as decorateHighlightedHtml,b as defaultMeta,R as escapeHtml,pe as hasMoreThanNLines,_ as inferIndentation,m as isIndentation,p as isSupportedLanguage,S as mantleCode,l as normalizeIndentation,h as normalizeValue,g as parseCodeBlockHighlightLines,y as parseCodeBlockLineNumberStart,s as parseCodeBlockShowLineNumbers,x as parseLanguage,v as parseMetastring,f as resolvePreRenderedCodeBlockProps,c as supportedLanguages,o as tokenizeMetastring};
3
3
  //# sourceMappingURL=code-block.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-block.js","names":["Root","RadixTabsRoot","MantleIcon","RadixTabsList","RadixTabsTrigger","RadixTabsContent"],"sources":["../src/components/code-block/escape-html.ts","../src/components/code-block/code-block.tsx","../src/components/code-block/mantle-code.ts","../src/components/code-block/has-more-than-n-lines.ts"],"sourcesContent":["/**\n * Escapes special HTML characters in a string to their corresponding\n * HTML entities, preventing issues like unintended HTML rendering or\n * cross-site scripting (XSS) when injecting raw strings into the DOM\n * using `dangerouslySetInnerHTML`.\n *\n * Characters escaped:\n * - \\& => `&amp;`;\n * - \\< => `&lt;`;\n * - \\> => `&gt;`;\n * - \\\" => `&quot;`;\n * - \\' => `&#39;`;\n *\n * @param {string} value The raw string to be escaped.\n *\n * @example\n * escapeHtml('<div>Hello & \"world\"</div>');\n * // Returns: '&lt;div&gt;Hello &amp; &quot;world&quot;&lt;/div&gt;'\n */\nfunction escapeHtml(value: string): string {\n\tlet firstSpecialCharIndex = -1;\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst character = value[i];\n\t\tif (\n\t\t\tcharacter === \"&\" ||\n\t\t\tcharacter === \"<\" ||\n\t\t\tcharacter === \">\" ||\n\t\t\tcharacter === '\"' ||\n\t\t\tcharacter === \"'\"\n\t\t) {\n\t\t\tfirstSpecialCharIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (firstSpecialCharIndex === -1) {\n\t\treturn value;\n\t}\n\n\tlet escaped = value.slice(0, firstSpecialCharIndex);\n\tfor (let i = firstSpecialCharIndex; i < value.length; i++) {\n\t\tconst character = value[i];\n\t\tswitch (character) {\n\t\t\tcase \"&\":\n\t\t\t\tescaped += \"&amp;\";\n\t\t\t\tbreak;\n\t\t\tcase \"<\":\n\t\t\t\tescaped += \"&lt;\";\n\t\t\t\tbreak;\n\t\t\tcase \">\":\n\t\t\t\tescaped += \"&gt;\";\n\t\t\t\tbreak;\n\t\t\tcase '\"':\n\t\t\t\tescaped += \"&quot;\";\n\t\t\t\tbreak;\n\t\t\tcase \"'\":\n\t\t\t\tescaped += \"&#39;\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tescaped += character;\n\t\t}\n\t}\n\treturn escaped;\n}\n\nexport {\n\t//,\n\tescapeHtml,\n};\n","\"use client\";\n\nimport { CaretDownIcon } from \"@phosphor-icons/react/CaretDown\";\nimport { CheckIcon } from \"@phosphor-icons/react/Check\";\nimport { CopyIcon } from \"@phosphor-icons/react/Copy\";\nimport { FileTextIcon } from \"@phosphor-icons/react/FileText\";\nimport { TerminalIcon } from \"@phosphor-icons/react/Terminal\";\nimport type {\n\tComponentProps,\n\tComponentRef,\n\tDispatch,\n\tHTMLAttributes,\n\tReactNode,\n\tSetStateAction,\n} from \"react\";\nimport {\n\tcreateContext,\n\tforwardRef,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseId,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tContent as RadixTabsContent,\n\tList as RadixTabsList,\n\tRoot as RadixTabsRoot,\n\tTrigger as RadixTabsTrigger,\n} from \"@radix-ui/react-tabs\";\nimport assert from \"tiny-invariant\";\nimport { useCopyToClipboard } from \"../../hooks/use-copy-to-clipboard.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Icon as MantleIcon } from \"../icon/icon.js\";\nimport type { SvgAttributes } from \"../icon/types.js\";\nimport { TrafficPolicyFileIcon } from \"../icons/traffic-policy-file.js\";\nimport { IconButton } from \"../button/icon-button.js\";\nimport { Slot } from \"../slot/index.js\";\nimport { escapeHtml } from \"./escape-html.js\";\nimport type { Mode } from \"./resolve-pre-rendered-props.js\";\nimport type { MantleCodeBlockValue } from \"./mantle-code.js\";\n\ntype CodeBlockContextType = {\n\tcodeId: string | undefined;\n\tcopyTextRef: { current: string };\n\thasCodeExpander: boolean;\n\tisCodeExpanded: boolean;\n\tregisterCodeId: (id: string) => void;\n\tsetHasCodeExpander: (value: boolean) => void;\n\tsetIsCodeExpanded: Dispatch<SetStateAction<boolean>>;\n\tunregisterCodeId: (id: string) => void;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType | null>(null);\n\n/** Returns the nearest `CodeBlock` context, throwing if called outside a `CodeBlock.Root`. */\nfunction useCodeBlockContext(): CodeBlockContextType {\n\tconst context = useContext(CodeBlockContext);\n\tassert(context != null, \"CodeBlock subcomponents must be rendered within a <CodeBlock.Root>.\");\n\treturn context;\n}\n\ntype CodeBlockRootProps = Omit<ComponentProps<\"div\">, \"align\"> &\n\tWithAsChild & {\n\t\t/**\n\t\t * The default active tab value (uncontrolled).\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tdefaultTab?: string;\n\t\t/**\n\t\t * The controlled active tab value.\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tactiveTab?: string;\n\t\t/**\n\t\t * Callback fired when the active tab changes.\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tonActiveTabChange?: (value: string) => void;\n\t};\n\n/**\n * Shiki-powered code blocks with build-time syntax highlighting and zero browser bundle.\n * This is the root component for all CodeBlock components.\n *\n * For tabbed code blocks, pass `defaultTab` (uncontrolled) or `activeTab` / `onActiveTabChange`\n * (controlled) to enable tab switching with `CodeBlock.TabList` and `CodeBlock.TabContent`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n * ```\n */\nconst Root = forwardRef<ComponentRef<\"div\">, CodeBlockRootProps>(\n\t({ asChild = false, className, defaultTab, activeTab, onActiveTabChange, ...props }, ref) => {\n\t\tconst copyTextRef = useRef(\"\");\n\t\tconst [hasCodeExpander, setHasCodeExpander] = useState(false);\n\t\tconst [isCodeExpanded, setIsCodeExpanded] = useState(false);\n\t\tconst [codeId, setCodeId] = useState<string | undefined>(undefined);\n\n\t\tconst registerCodeId = useCallback((id: string) => {\n\t\t\tsetCodeId((old) => {\n\t\t\t\tassert(old == null, \"You can only render a single CodeBlock.Code within a CodeBlock.\");\n\t\t\t\treturn id;\n\t\t\t});\n\t\t}, []);\n\n\t\tconst unregisterCodeId = useCallback((id: string) => {\n\t\t\tsetCodeId((old) => {\n\t\t\t\tassert(old === id, \"You can only render a single CodeBlock.Code within a CodeBlock.\");\n\t\t\t\treturn undefined;\n\t\t\t});\n\t\t}, []);\n\n\t\tconst context: CodeBlockContextType = useMemo(\n\t\t\t() =>\n\t\t\t\t({\n\t\t\t\t\tcodeId,\n\t\t\t\t\tcopyTextRef,\n\t\t\t\t\thasCodeExpander,\n\t\t\t\t\tisCodeExpanded,\n\t\t\t\t\tregisterCodeId,\n\t\t\t\t\tsetHasCodeExpander,\n\t\t\t\t\tsetIsCodeExpanded,\n\t\t\t\t\tunregisterCodeId,\n\t\t\t\t}) as const,\n\t\t\t[codeId, hasCodeExpander, isCodeExpanded, registerCodeId, unregisterCodeId],\n\t\t);\n\n\t\tconst hasTabs = defaultTab !== undefined || activeTab !== undefined;\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\tconst tree = (\n\t\t\t<Component\n\t\t\t\tdata-slot=\"code-block\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-mono w-full overflow-hidden rounded-md border border-gray-300 bg-card font-mono\",\n\t\t\t\t\t\"[&_svg]:shrink-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\n\t\treturn (\n\t\t\t<CodeBlockContext.Provider value={context}>\n\t\t\t\t{hasTabs ? (\n\t\t\t\t\t<RadixTabsRoot\n\t\t\t\t\t\tasChild\n\t\t\t\t\t\tdefaultValue={defaultTab}\n\t\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\t\tonValueChange={onActiveTabChange}\n\t\t\t\t\t>\n\t\t\t\t\t\t{tree}\n\t\t\t\t\t</RadixTabsRoot>\n\t\t\t\t) : (\n\t\t\t\t\ttree\n\t\t\t\t)}\n\t\t\t</CodeBlockContext.Provider>\n\t\t);\n\t},\n);\nRoot.displayName = \"CodeBlock\";\n\n/**\n * The body of the `CodeBlock`. This is where `CodeBlock.Code` and\n * the optional `CodeBlock.CopyButton` are rendered.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * </CodeBlock.Root>\n * ```\n */\nconst Body = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild = false, className, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\t\treturn <Component className={cx(\"relative\", className)} ref={ref} {...props} />;\n\t},\n);\nBody.displayName = \"CodeBlockBody\";\n\n/**\n * Matches `SHIKI_VAL_<index>` placeholders injected by the Vite plugin for\n * interpolated template expressions. Hoisted to module scope to avoid\n * re-creating the regex on every substitution call.\n */\nconst LEGACY_SHIKI_VAL_PATTERN = /SHIKI_VAL_(\\d+)/g;\n\n/** Escapes special characters in a string for use in a `RegExp` constructor. */\nfunction escapeForRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst maxPreValPatternCacheSize = 500;\nconst preValPatternCache = new Map<string, RegExp>();\n\n/**\n * Returns the cached `RegExp` for the given `preValToken`, falling back to the\n * legacy `SHIKI_VAL_<n>` pattern when no token is provided.\n */\nfunction getTemplateValPattern(preValToken: string | undefined): RegExp {\n\tif (preValToken == null || preValToken.length === 0) {\n\t\treturn LEGACY_SHIKI_VAL_PATTERN;\n\t}\n\n\tlet cached = preValPatternCache.get(preValToken);\n\tif (cached == null) {\n\t\tif (preValPatternCache.size >= maxPreValPatternCacheSize) {\n\t\t\tpreValPatternCache.clear();\n\t\t}\n\t\tcached = new RegExp(`${escapeForRegExp(preValToken)}(\\\\d+)__`, \"g\");\n\t\tpreValPatternCache.set(preValToken, cached);\n\t}\n\treturn cached;\n}\n\n/**\n * Replaces placeholder tokens in `input` with values from `vals`, applying\n * `mapValue` to each substituted value. Returns the input unchanged when\n * no placeholders are present.\n */\nfunction substituteTemplateVals(\n\tinput: string,\n\tvals: unknown[],\n\tpreValToken: string | undefined,\n\tmapValue: (value: unknown) => string,\n): string {\n\tif (preValToken == null) {\n\t\tif (!input.includes(\"SHIKI_VAL_\")) {\n\t\t\treturn input;\n\t\t}\n\t} else if (!input.includes(preValToken)) {\n\t\treturn input;\n\t}\n\n\treturn input.replaceAll(getTemplateValPattern(preValToken), (match, indexText: string) => {\n\t\tconst index = Number.parseInt(indexText, 10);\n\t\tif (Number.isNaN(index) || index < 0 || index >= vals.length) {\n\t\t\treturn match;\n\t\t}\n\t\treturn mapValue(vals[index]);\n\t});\n}\n\n/** Substitutes placeholder tokens in pre-rendered HTML, HTML-escaping each interpolated value. */\nfunction substitutePreVals(html: string, vals: unknown[], preValToken: string | undefined): string {\n\treturn substituteTemplateVals(html, vals, preValToken, (value) => escapeHtml(String(value)));\n}\n\n/** Substitutes placeholder tokens in plain text (for the copy button), without HTML escaping. */\nfunction substitutePreValsPlainText(\n\ttext: string,\n\tvals: unknown[],\n\tpreValToken: string | undefined,\n): string {\n\treturn substituteTemplateVals(text, vals, preValToken, (value) => String(value));\n}\n\ntype CodeBlockCodeProps = Omit<ComponentProps<\"pre\">, \"children\"> & {\n\t/**\n\t * The code value produced by `mantleCode(\"lang\")` tagged template.\n\t * Contains pre-rendered Shiki HTML (when the Vite plugin is active) and\n\t * the original code string for the copy button.\n\t */\n\tvalue: MantleCodeBlockValue;\n};\n\n/**\n * The `CodeBlock` content. Renders pre-highlighted code from `mantleCode()`.\n *\n * `value[\"~preHtml\"]` must be provided by Mantle's Vite plugin or server highlighter.\n * Runtime highlighting and runtime line decoration are intentionally unsupported.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * ```\n */\nconst Code = forwardRef<ComponentRef<\"pre\">, CodeBlockCodeProps>(\n\t({ className, style, tabIndex, value, ...props }, ref) => {\n\t\tconst id = useId();\n\t\tconst { copyTextRef, hasCodeExpander, isCodeExpanded, registerCodeId, unregisterCodeId } =\n\t\t\tuseCodeBlockContext();\n\t\tconst {\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\t\"~preValToken\": __preValToken,\n\t\t\t\"~preVals\": __preVals,\n\t\t\t\"~highlightLines\": __highlightLines,\n\t\t\t\"~lineNumberStart\": __lineNumberStart,\n\t\t\t\"~preHtml\": __preHtml,\n\t\t\t\"~showLineNumbers\": __showLineNumbers,\n\t\t} = value;\n\n\t\tconst effectiveHighlightLines = __highlightLines;\n\t\tconst effectiveLineNumberStart = __lineNumberStart ?? 1;\n\t\tconst effectiveShowLineNumbers = __showLineNumbers ?? false;\n\t\tconst copyText = useMemo(\n\t\t\t() =>\n\t\t\t\t__preVals != null && __preVals.length > 0\n\t\t\t\t\t? substitutePreValsPlainText(code, __preVals, __preValToken)\n\t\t\t\t\t: code,\n\t\t\t[__preValToken, __preVals, code],\n\t\t);\n\n\t\tuseLayoutEffect(() => {\n\t\t\tcopyTextRef.current = copyText;\n\t\t}, [copyTextRef, copyText]);\n\n\t\tuseEffect(() => {\n\t\t\tregisterCodeId(id);\n\n\t\t\treturn () => {\n\t\t\t\tunregisterCodeId(id);\n\t\t\t};\n\t\t}, [id, registerCodeId, unregisterCodeId]);\n\n\t\tconst renderedHtml = useMemo(() => {\n\t\t\tif (__preHtml == null) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn __preVals != null && __preVals.length > 0\n\t\t\t\t? substitutePreVals(__preHtml, __preVals, __preValToken)\n\t\t\t\t: __preHtml;\n\t\t}, [__preHtml, __preValToken, __preVals]);\n\n\t\tconst isPreRendered = renderedHtml != null;\n\t\tconst displayHtml = renderedHtml ?? escapeHtml(copyText);\n\n\t\treturn (\n\t\t\t<pre\n\t\t\t\taria-expanded={hasCodeExpander ? isCodeExpanded : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"scrollbar overflow-x-auto overflow-y-hidden py-4\",\n\t\t\t\t\t!isPreRendered && \"pr-14\",\n\t\t\t\t\t\"data-[mantle-line-numbers~='false']:pl-4\",\n\t\t\t\t\t\"text-mono m-0 font-mono\",\n\t\t\t\t\t\"aria-collapsed:max-h-[13.6rem]\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-highlighted={isPreRendered ? \"true\" : \"false\"}\n\t\t\t\tdata-lang={language}\n\t\t\t\tdata-mantle-highlight-lines={\n\t\t\t\t\tisPreRendered && effectiveHighlightLines != null && effectiveHighlightLines.length > 0\n\t\t\t\t\t\t? effectiveHighlightLines.join(\",\")\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-mantle-line-number-start={\n\t\t\t\t\tisPreRendered && effectiveShowLineNumbers ? String(effectiveLineNumberStart) : \"1\"\n\t\t\t\t}\n\t\t\t\tdata-mantle-line-numbers={isPreRendered && effectiveShowLineNumbers ? \"true\" : \"false\"}\n\t\t\t\tid={id}\n\t\t\t\tref={ref}\n\t\t\t\tstyle={\n\t\t\t\t\t{\n\t\t\t\t\t\t...style,\n\t\t\t\t\t\t\"--mantle-line-number-start\": String(effectiveLineNumberStart),\n\t\t\t\t\t\ttabSize: 2,\n\t\t\t\t\t\tMozTabSize: 2,\n\t\t\t\t\t} as ComponentProps<\"pre\">[\"style\"]\n\t\t\t\t}\n\t\t\t\ttabIndex={tabIndex ?? -1}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<code\n\t\t\t\t\tclassName=\"text-size-inherit block min-w-full w-max\"\n\t\t\t\t\tdangerouslySetInnerHTML={{ __html: displayHtml }}\n\t\t\t\t/>\n\t\t\t</pre>\n\t\t);\n\t},\n);\nCode.displayName = \"CodeBlockCode\";\n\n/**\n * The (optional) header slot of the `CodeBlock`. This is where\n * `CodeBlock.Icon` and `CodeBlock.Title` are rendered.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * </CodeBlock.Root>\n * ```\n */\nconst Header = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild = false, className, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"flex items-center gap-1 border-b border-gray-300 bg-base px-4 py-2 text-gray-700\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nHeader.displayName = \"CodeBlockHeader\";\n\n/**\n * The (optional) title of the `CodeBlock`. Renders as `h3` by default;\n * use `asChild` to render a different element.\n *\n * @example\n * ```tsx\n * <CodeBlock.Header>\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * ```\n */\nconst Title = forwardRef<\n\tHTMLHeadingElement,\n\tHTMLAttributes<HTMLHeadingElement> & { asChild?: boolean }\n>(({ asChild = false, className, ...props }, ref) => {\n\tconst Component = asChild ? Slot : \"h3\";\n\treturn (\n\t\t<Component\n\t\t\tref={ref}\n\t\t\tclassName={cx(\"text-mono m-0 font-mono font-normal\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nTitle.displayName = \"CodeBlockTitle\";\n\ntype CodeBlockCopyButtonProps = Omit<ComponentProps<\"button\">, \"children\" | \"type\"> & {\n\t/**\n\t * Callback fired when the copy button is clicked, passes the copied text as an argument.\n\t */\n\tonCopy?: (value: string) => void;\n\t/**\n\t * Callback fired when an error occurs during copying.\n\t */\n\tonCopyError?: (error: unknown) => void;\n};\n\n/**\n * The (optional) copy button of the `CodeBlock`. Copies the code content\n * to the clipboard when clicked.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`…`} />\n * </CodeBlock.Body>\n * ```\n */\nconst CopyButton = forwardRef<ComponentRef<\"button\">, CodeBlockCopyButtonProps>(\n\t({ className, onCopy, onCopyError, onClick, ...props }, ref) => {\n\t\tconst { copyTextRef } = useCodeBlockContext();\n\t\tconst [, copyToClipboard] = useCopyToClipboard();\n\t\tconst [wasCopied, setWasCopied] = useState(false);\n\t\tconst timeoutHandle = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n\t\tuseEffect(() => {\n\t\t\treturn () => {\n\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t}\n\t\t\t};\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<span className=\"absolute right-2.5 top-2.5 z-10 bg-card\">\n\t\t\t\t<IconButton\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tlabel=\"Copy code\"\n\t\t\t\t\ticon={wasCopied ? <CheckIcon /> : <CopyIcon />}\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tref={ref}\n\t\t\t\t\tonClick={async (event) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tonClick?.(event);\n\t\t\t\t\t\t\tif (event.defaultPrevented) {\n\t\t\t\t\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst text = copyTextRef.current;\n\t\t\t\t\t\t\tawait copyToClipboard(text);\n\t\t\t\t\t\t\tonCopy?.(text);\n\t\t\t\t\t\t\tsetWasCopied(true);\n\t\t\t\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimeoutHandle.current = setTimeout(() => {\n\t\t\t\t\t\t\t\tsetWasCopied(false);\n\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tonCopyError?.(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t</span>\n\t\t);\n\t},\n);\nCopyButton.displayName = \"CodeBlockCopyButton\";\n\ntype CodeBlockExpanderButtonProps = Omit<\n\tComponentProps<\"button\">,\n\t\"children\" | \"aria-controls\" | \"aria-expanded\"\n> &\n\tWithAsChild;\n\n/**\n * The (optional) expander button of the `CodeBlock`. Toggles the expanded\n * state of the code block. When present, the code block is collapsible.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Body>\n * <CodeBlock.Code value={mantleCode(\"typescript\")`…`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n * ```\n */\nconst ExpanderButton = forwardRef<ComponentRef<\"button\">, CodeBlockExpanderButtonProps>(\n\t({ asChild = false, className, onClick, ...props }, ref) => {\n\t\tconst { codeId, isCodeExpanded, setIsCodeExpanded, setHasCodeExpander } = useCodeBlockContext();\n\n\t\tuseEffect(() => {\n\t\t\tsetHasCodeExpander(true);\n\t\t\treturn () => {\n\t\t\t\tsetHasCodeExpander(false);\n\t\t\t};\n\t\t}, [setHasCodeExpander]);\n\n\t\tconst Component = asChild ? Slot : \"button\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\t{...props}\n\t\t\t\taria-controls={codeId}\n\t\t\t\taria-expanded={isCodeExpanded}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"flex w-full items-center justify-center gap-0.5 border-t border-gray-300 bg-card px-4 py-2 font-sans text-gray-700 hover:bg-gray-100\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\tsetIsCodeExpanded((prev) => !prev);\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{isCodeExpanded ? \"Show less\" : \"Show more\"}{\" \"}\n\t\t\t\t<MantleIcon\n\t\t\t\t\tsvg={<CaretDownIcon weight=\"bold\" />}\n\t\t\t\t\tclassName={cx(\"size-4\", isCodeExpanded && \"rotate-180\", \"transition-all duration-150\")}\n\t\t\t\t/>\n\t\t\t</Component>\n\t\t);\n\t},\n);\nExpanderButton.displayName = \"CodeBlockExpanderButton\";\n\ntype CodeBlockIconProps = Omit<SvgAttributes, \"children\"> &\n\t(\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * A custom icon SVG to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tsvg: ReactNode;\n\t\t\t\t/**\n\t\t\t\t * A preset icon to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tpreset?: undefined | never;\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * A custom icon SVG to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tsvg?: undefined | never;\n\t\t\t\t/**\n\t\t\t\t * A preset icon to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tpreset: Mode;\n\t\t }\n\t);\n\n/**\n * A small icon for the `CodeBlock` header. Pass either a custom `svg`\n * or a `preset` value (not both).\n *\n * @example\n * ```tsx\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * ```\n */\nfunction CodeBlockIconComponent({\n\tclassName,\n\tpreset,\n\tsvg: _svgProp,\n\t...props\n}: CodeBlockIconProps) {\n\tlet svg = _svgProp;\n\tif (preset != null) {\n\t\tswitch (preset) {\n\t\t\tcase \"file\":\n\t\t\t\tsvg = <FileTextIcon weight=\"fill\" />;\n\t\t\t\tbreak;\n\t\t\tcase \"cli\":\n\t\t\t\tsvg = <TerminalIcon weight=\"fill\" />;\n\t\t\t\tbreak;\n\t\t\tcase \"traffic-policy\":\n\t\t\t\tsvg = <TrafficPolicyFileIcon />;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn <MantleIcon className={className} svg={svg} {...props} />;\n}\nCodeBlockIconComponent.displayName = \"CodeBlockIcon\";\n\ntype CodeBlockTabListProps = Omit<ComponentProps<typeof RadixTabsList>, \"asChild\" | \"loop\">;\n\n/**\n * A tab list for the `CodeBlock` header. Renders pill-styled tab triggers\n * that switch which code is displayed. Built on Radix Tabs primitives.\n *\n * Place this inside `CodeBlock.Header` and pair with `CodeBlock.TabContent`\n * in `CodeBlock.Body` to conditionally render code based on the active tab.\n * Tab state is managed by `CodeBlock.Root` via `defaultTab` / `activeTab` / `onActiveTabChange`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root defaultTab=\"yml\">\n * <CodeBlock.Header>\n * <CodeBlock.TabList>\n * <CodeBlock.TabTrigger value=\"yml\">policy.yml</CodeBlock.TabTrigger>\n * <CodeBlock.TabTrigger value=\"json\">policy.json</CodeBlock.TabTrigger>\n * </CodeBlock.TabList>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.TabContent value=\"yml\">\n * <CodeBlock.Code value={ymlValue} />\n * </CodeBlock.TabContent>\n * <CodeBlock.TabContent value=\"json\">\n * <CodeBlock.Code value={jsonValue} />\n * </CodeBlock.TabContent>\n * </CodeBlock.Body>\n * </CodeBlock.Root>\n * ```\n */\nconst TabList = forwardRef<ComponentRef<typeof RadixTabsList>, CodeBlockTabListProps>(\n\t({ className, ...props }, ref) => (\n\t\t<RadixTabsList className={cx(\"flex items-center gap-1\", className)} ref={ref} {...props} />\n\t),\n);\nTabList.displayName = \"CodeBlockTabList\";\n\ntype CodeBlockTabTriggerProps = Omit<ComponentProps<typeof RadixTabsTrigger>, \"asChild\">;\n\n/**\n * A pill-styled tab trigger for the `CodeBlock` header.\n * Must be rendered within a `CodeBlock.TabList`.\n *\n * @example\n * ```tsx\n * <CodeBlock.TabList>\n * <CodeBlock.TabTrigger value=\"yml\">policy.yml</CodeBlock.TabTrigger>\n * <CodeBlock.TabTrigger value=\"json\">policy.json</CodeBlock.TabTrigger>\n * </CodeBlock.TabList>\n * ```\n */\nconst TabTrigger = forwardRef<ComponentRef<typeof RadixTabsTrigger>, CodeBlockTabTriggerProps>(\n\t({ className, ...props }, ref) => (\n\t\t<RadixTabsTrigger\n\t\t\tclassName={cx(\n\t\t\t\t\"cursor-pointer rounded px-1.5 py-0.5 text-xs font-medium\",\n\t\t\t\t\"text-gray-600 outline-hidden\",\n\t\t\t\t\"hover:text-gray-900\",\n\t\t\t\t\"data-[state=active]:bg-neutral-500/15 data-[state=active]:text-strong\",\n\t\t\t\t\"focus-visible:ring-focus-accent focus-visible:ring-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nTabTrigger.displayName = \"CodeBlockTabTrigger\";\n\ntype CodeBlockTabContentProps = Omit<\n\tComponentProps<typeof RadixTabsContent>,\n\t\"asChild\" | \"forceMount\"\n>;\n\n/**\n * Conditionally renders its children when the associated tab is active.\n * Pair with `CodeBlock.TabList` and `CodeBlock.TabTrigger` in the header,\n * and set `defaultTab` / `activeTab` on `CodeBlock.Root`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.TabContent value=\"yml\">\n * <CodeBlock.Code value={ymlValue} />\n * </CodeBlock.TabContent>\n * <CodeBlock.TabContent value=\"json\">\n * <CodeBlock.Code value={jsonValue} />\n * </CodeBlock.TabContent>\n * </CodeBlock.Body>\n * ```\n */\nconst TabContent = forwardRef<ComponentRef<typeof RadixTabsContent>, CodeBlockTabContentProps>(\n\t(props, ref) => <RadixTabsContent ref={ref} {...props} />,\n);\nTabContent.displayName = \"CodeBlockTabContent\";\n\n/**\n * Shiki-powered code blocks with build-time syntax highlighting and zero browser bundle.\n *\n * Use `mantleCodeBlockPlugins()` to enable pre-rendering at build time.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n *\n * // Server-highlighted HTML fetched via an action route + React Query mutation\n * const highlightMutation = useMutation({\n * mutationFn: async () => {\n * const response = await fetch(\"/api/shiki-highlight\", {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({ code: source, language: \"typescript\" }),\n * });\n * return response.json();\n * },\n * });\n *\n * const serverValue = createMantleCodeBlockValue({\n * language: \"typescript\",\n * code: source,\n * preHtml: highlightMutation.data?.html,\n * });\n * ```\n */\nconst CodeBlock = {\n\t/**\n\t * The root component of the `CodeBlock`.\n\t */\n\tRoot,\n\t/**\n\t * The body of the `CodeBlock`. Contains `Code` and optional `CopyButton`.\n\t */\n\tBody,\n\t/**\n\t * The code content. Renders pre-highlighted Shiki HTML when the Vite plugin is active.\n\t */\n\tCode,\n\t/**\n\t * The optional copy button.\n\t */\n\tCopyButton,\n\t/**\n\t * The optional expander button for collapsible code blocks.\n\t */\n\tExpanderButton,\n\t/**\n\t * The optional header slot for icon and title.\n\t */\n\tHeader,\n\t/**\n\t * A small icon for the code block header. Use `preset` or `svg`.\n\t */\n\tIcon: CodeBlockIconComponent,\n\t/**\n\t * Conditionally renders children when the associated tab is active.\n\t */\n\tTabContent,\n\t/**\n\t * A tab list for the code block header. Renders pill-styled tabs for switching code.\n\t */\n\tTabList,\n\t/**\n\t * A pill-styled tab trigger for the code block header. Must be inside `TabList`.\n\t */\n\tTabTrigger,\n\t/**\n\t * The optional title rendered in the header.\n\t */\n\tTitle,\n} as const;\n\nexport {\n\t//,\n\tCodeBlock,\n};\n","import type { SupportedLanguage } from \"../code-block/supported-languages.js\";\nimport type { LineRange } from \"../code-block/line-numbers.js\";\nimport type { Indentation } from \"../code-block/indentation.js\";\n\nconst mantleCodeBlockValueBrand: unique symbol = Symbol(\"MantleCodeBlockValue\");\n\n/**\n * The value produced by `mantleCode()`. Contains pre-rendered Shiki HTML (injected\n * by the Vite plugin at build time) and the original code string for the copy button.\n *\n * `~preHtml` is required at render time. Runtime syntax highlighting is intentionally\n * unsupported; only placeholder substitution for interpolated values is performed.\n */\ntype MantleCodeBlockValue = {\n\t/**\n\t * Nominal type brand to prevent accidental use of plain objects.\n\t */\n\t[mantleCodeBlockValueBrand]: true;\n\t/**\n\t * The language used for syntax highlighting.\n\t */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * The original code string (used by the copy button).\n\t */\n\tcode: string;\n\t/**\n\t * Fully pre-rendered Shiki HTML injected by the Vite plugin or server highlighter.\n\t * This must be present for rendering.\n\t *\n\t * **Security:** This HTML is injected via `dangerouslySetInnerHTML`. It must\n\t * come from a trusted source (Shiki output from the Vite plugin or\n\t * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input.\n\t */\n\t\"~preHtml\"?: string | undefined;\n\t/**\n\t * Runtime values used to replace `SHIKI_VAL_N` placeholders in `~preHtml`.\n\t * This enables interpolated template expressions while preserving build-time highlighting.\n\t */\n\t\"~preVals\"?: unknown[] | undefined;\n\t/**\n\t * Placeholder token prefix used by the Vite transform for interpolated values.\n\t * When omitted, CodeBlock falls back to the legacy `SHIKI_VAL_<n>` format.\n\t */\n\t\"~preValToken\"?: string | undefined;\n\t/**\n\t * Optional default for line-number rendering when this value is displayed.\n\t */\n\t\"~showLineNumbers\"?: boolean | undefined;\n\t/**\n\t * Optional default highlighted line numbers/ranges when this value is displayed.\n\t */\n\t\"~highlightLines\"?: (LineRange | number)[] | undefined;\n\t/**\n\t * Optional default start line number when line numbers are displayed.\n\t * @default 1\n\t */\n\t\"~lineNumberStart\"?: number | undefined;\n};\n\n/** Maps each key starting with `OldPrefix` to `NewPrefix`, leaving other keys unchanged. */\ntype ReplacePrefix<T, OldPrefix extends string, NewPrefix extends string> = {\n\t[K in keyof T as K extends `${OldPrefix}${infer Rest}` ? `${NewPrefix}${Rest}` : K]: T[K];\n};\n\n/** Public input shape for `createMantleCodeBlockValue`, with `~`-prefixed keys renamed to unprefixed. */\ntype MantleCodeBlockValueInput = ReplacePrefix<\n\tOmit<MantleCodeBlockValue, typeof mantleCodeBlockValueBrand>,\n\t\"~\",\n\t\"\"\n>;\n\n/** Options for configuring line numbers, highlights, and indentation in `mantleCode()`. */\ntype MantleCodeOptions = {\n\thighlightLines?: (LineRange | number)[] | undefined;\n\tindentation?: Indentation | undefined;\n\tlineNumberStart?: number | undefined;\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Creates a `MantleCodeBlockValue` for use with `CodeBlock.Code`.\n *\n * **Security:** The `preHtml` field is rendered via `dangerouslySetInnerHTML`.\n * Only pass HTML produced by Shiki (via the Vite plugin or\n * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input as `preHtml`.\n */\nfunction createMantleCodeBlockValue({\n\tpreHtml,\n\tpreValToken,\n\tpreVals,\n\thighlightLines,\n\tlineNumberStart,\n\tshowLineNumbers,\n\tcode,\n\tlanguage,\n}: MantleCodeBlockValueInput): MantleCodeBlockValue {\n\treturn {\n\t\t[mantleCodeBlockValueBrand]: true,\n\t\tlanguage,\n\t\tcode,\n\t\t\"~preHtml\": preHtml,\n\t\t\"~preValToken\": preValToken,\n\t\t\"~preVals\": preVals,\n\t\t\"~highlightLines\": highlightLines,\n\t\t\"~lineNumberStart\": lineNumberStart,\n\t\t\"~showLineNumbers\": showLineNumbers,\n\t};\n}\n\n/** Joins a `TemplateStringsArray` and its interpolated values into a single code string. */\nfunction buildCodeFromTemplate(strings: TemplateStringsArray, values: unknown[]): string {\n\tlet code = \"\";\n\tfor (let index = 0; index < strings.length; index += 1) {\n\t\tcode += strings[index] ?? \"\";\n\t\tif (index < values.length) {\n\t\t\tcode += String(values[index]);\n\t\t}\n\t}\n\treturn code;\n}\n\n/**\n * Tagged template literal for Shiki syntax highlighting.\n *\n * Returns a `MantleCodeBlockValue` that `CodeBlock.Code` renders.\n * The Vite transform plugin rewrites calls to this function at build time,\n * inlining pre-rendered Shiki HTML so that no highlighting work happens in the browser.\n * Configure it via `mantleCodeBlockPlugins()` in `vite.config.ts`.\n *\n * Interpolated template expressions are supported via placeholder substitution.\n *\n * @example\n * ```tsx\n * // Static string\n * mantleCode(\"typescript\")`const x: string = \"hello\";`\n * // Interpolated string\n * mantleCode(\"typescript\")`const greeting = \"Hello, ${name}!\";`\n * ```\n */\nfunction mantleCode(\n\tlanguage: SupportedLanguage,\n\toptions: MantleCodeOptions = {},\n): (strings: TemplateStringsArray, ...values: unknown[]) => MantleCodeBlockValue {\n\treturn (strings, ...values) => {\n\t\tconst code = buildCodeFromTemplate(strings, values);\n\n\t\treturn createMantleCodeBlockValue({\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\tpreHtml: undefined,\n\t\t\tpreVals: values.length > 0 ? values : undefined,\n\t\t\thighlightLines: options.highlightLines,\n\t\t\tlineNumberStart: options.lineNumberStart,\n\t\t\tshowLineNumbers: options.showLineNumbers,\n\t\t});\n\t};\n}\n\nexport { mantleCode };\nexport { createMantleCodeBlockValue };\nexport type { MantleCodeBlockValue, MantleCodeOptions };\n","/**\n * Returns `true` if `value` has more than `maxLines` newline-delimited lines.\n *\n * This is equivalent to `value.split(\"\\\\n\").length > maxLines`, but avoids\n * allocating an intermediate array and can early-return once the threshold is exceeded.\n */\nfunction hasMoreThanNLines(value: string, maxLines: number): boolean {\n\tlet lines = 1;\n\tif (lines > maxLines) {\n\t\treturn true;\n\t}\n\n\tfor (let i = 0; i < value.length; i++) {\n\t\tif (value[i] === \"\\n\") {\n\t\t\tlines += 1;\n\t\t\tif (lines > maxLines) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nexport {\n\t//,\n\thasMoreThanNLines,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"code-block.js","names":["Root","RadixTabsRoot","MantleIcon","RadixTabsList","RadixTabsTrigger","RadixTabsContent"],"sources":["../src/components/code-block/escape-html.ts","../src/components/code-block/code-block.tsx","../src/components/code-block/has-more-than-n-lines.ts"],"sourcesContent":["/**\n * Escapes special HTML characters in a string to their corresponding\n * HTML entities, preventing issues like unintended HTML rendering or\n * cross-site scripting (XSS) when injecting raw strings into the DOM\n * using `dangerouslySetInnerHTML`.\n *\n * Characters escaped:\n * - \\& => `&amp;`;\n * - \\< => `&lt;`;\n * - \\> => `&gt;`;\n * - \\\" => `&quot;`;\n * - \\' => `&#39;`;\n *\n * @param {string} value The raw string to be escaped.\n *\n * @example\n * escapeHtml('<div>Hello & \"world\"</div>');\n * // Returns: '&lt;div&gt;Hello &amp; &quot;world&quot;&lt;/div&gt;'\n */\nfunction escapeHtml(value: string): string {\n\tlet firstSpecialCharIndex = -1;\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst character = value[i];\n\t\tif (\n\t\t\tcharacter === \"&\" ||\n\t\t\tcharacter === \"<\" ||\n\t\t\tcharacter === \">\" ||\n\t\t\tcharacter === '\"' ||\n\t\t\tcharacter === \"'\"\n\t\t) {\n\t\t\tfirstSpecialCharIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (firstSpecialCharIndex === -1) {\n\t\treturn value;\n\t}\n\n\tlet escaped = value.slice(0, firstSpecialCharIndex);\n\tfor (let i = firstSpecialCharIndex; i < value.length; i++) {\n\t\tconst character = value[i];\n\t\tswitch (character) {\n\t\t\tcase \"&\":\n\t\t\t\tescaped += \"&amp;\";\n\t\t\t\tbreak;\n\t\t\tcase \"<\":\n\t\t\t\tescaped += \"&lt;\";\n\t\t\t\tbreak;\n\t\t\tcase \">\":\n\t\t\t\tescaped += \"&gt;\";\n\t\t\t\tbreak;\n\t\t\tcase '\"':\n\t\t\t\tescaped += \"&quot;\";\n\t\t\t\tbreak;\n\t\t\tcase \"'\":\n\t\t\t\tescaped += \"&#39;\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tescaped += character;\n\t\t}\n\t}\n\treturn escaped;\n}\n\nexport {\n\t//,\n\tescapeHtml,\n};\n","\"use client\";\n\nimport { CaretDownIcon } from \"@phosphor-icons/react/CaretDown\";\nimport { CheckIcon } from \"@phosphor-icons/react/Check\";\nimport { CopyIcon } from \"@phosphor-icons/react/Copy\";\nimport { FileTextIcon } from \"@phosphor-icons/react/FileText\";\nimport { TerminalIcon } from \"@phosphor-icons/react/Terminal\";\nimport type {\n\tComponentProps,\n\tComponentRef,\n\tDispatch,\n\tHTMLAttributes,\n\tReactNode,\n\tSetStateAction,\n} from \"react\";\nimport {\n\tcreateContext,\n\tforwardRef,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseId,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tContent as RadixTabsContent,\n\tList as RadixTabsList,\n\tRoot as RadixTabsRoot,\n\tTrigger as RadixTabsTrigger,\n} from \"@radix-ui/react-tabs\";\nimport assert from \"tiny-invariant\";\nimport { useCopyToClipboard } from \"../../hooks/use-copy-to-clipboard.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Icon as MantleIcon } from \"../icon/icon.js\";\nimport type { SvgAttributes } from \"../icon/types.js\";\nimport { TrafficPolicyFileIcon } from \"../icons/traffic-policy-file.js\";\nimport { IconButton } from \"../button/icon-button.js\";\nimport { Slot } from \"../slot/index.js\";\nimport { escapeHtml } from \"./escape-html.js\";\nimport type { Mode } from \"./resolve-pre-rendered-props.js\";\nimport type { MantleCodeBlockValue } from \"./mantle-code.js\";\n\ntype CodeBlockContextType = {\n\tcodeId: string | undefined;\n\tcopyTextRef: { current: string };\n\thasCodeExpander: boolean;\n\tisCodeExpanded: boolean;\n\tregisterCodeId: (id: string) => void;\n\tsetHasCodeExpander: (value: boolean) => void;\n\tsetIsCodeExpanded: Dispatch<SetStateAction<boolean>>;\n\tunregisterCodeId: (id: string) => void;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType | null>(null);\n\n/** Returns the nearest `CodeBlock` context, throwing if called outside a `CodeBlock.Root`. */\nfunction useCodeBlockContext(): CodeBlockContextType {\n\tconst context = useContext(CodeBlockContext);\n\tassert(context != null, \"CodeBlock subcomponents must be rendered within a <CodeBlock.Root>.\");\n\treturn context;\n}\n\ntype CodeBlockRootProps = Omit<ComponentProps<\"div\">, \"align\"> &\n\tWithAsChild & {\n\t\t/**\n\t\t * The default active tab value (uncontrolled).\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tdefaultTab?: string;\n\t\t/**\n\t\t * The controlled active tab value.\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tactiveTab?: string;\n\t\t/**\n\t\t * Callback fired when the active tab changes.\n\t\t * Only relevant when using `CodeBlock.TabList` / `CodeBlock.TabContent`.\n\t\t */\n\t\tonActiveTabChange?: (value: string) => void;\n\t};\n\n/**\n * Shiki-powered code blocks with build-time syntax highlighting and zero browser bundle.\n * This is the root component for all CodeBlock components.\n *\n * For tabbed code blocks, pass `defaultTab` (uncontrolled) or `activeTab` / `onActiveTabChange`\n * (controlled) to enable tab switching with `CodeBlock.TabList` and `CodeBlock.TabContent`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n * ```\n */\nconst Root = forwardRef<ComponentRef<\"div\">, CodeBlockRootProps>(\n\t({ asChild = false, className, defaultTab, activeTab, onActiveTabChange, ...props }, ref) => {\n\t\tconst copyTextRef = useRef(\"\");\n\t\tconst [hasCodeExpander, setHasCodeExpander] = useState(false);\n\t\tconst [isCodeExpanded, setIsCodeExpanded] = useState(false);\n\t\tconst [codeId, setCodeId] = useState<string | undefined>(undefined);\n\n\t\tconst registerCodeId = useCallback((id: string) => {\n\t\t\tsetCodeId((old) => {\n\t\t\t\tassert(old == null, \"You can only render a single CodeBlock.Code within a CodeBlock.\");\n\t\t\t\treturn id;\n\t\t\t});\n\t\t}, []);\n\n\t\tconst unregisterCodeId = useCallback((id: string) => {\n\t\t\tsetCodeId((old) => {\n\t\t\t\tassert(old === id, \"You can only render a single CodeBlock.Code within a CodeBlock.\");\n\t\t\t\treturn undefined;\n\t\t\t});\n\t\t}, []);\n\n\t\tconst context: CodeBlockContextType = useMemo(\n\t\t\t() =>\n\t\t\t\t({\n\t\t\t\t\tcodeId,\n\t\t\t\t\tcopyTextRef,\n\t\t\t\t\thasCodeExpander,\n\t\t\t\t\tisCodeExpanded,\n\t\t\t\t\tregisterCodeId,\n\t\t\t\t\tsetHasCodeExpander,\n\t\t\t\t\tsetIsCodeExpanded,\n\t\t\t\t\tunregisterCodeId,\n\t\t\t\t}) as const,\n\t\t\t[codeId, hasCodeExpander, isCodeExpanded, registerCodeId, unregisterCodeId],\n\t\t);\n\n\t\tconst hasTabs = defaultTab !== undefined || activeTab !== undefined;\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\tconst tree = (\n\t\t\t<Component\n\t\t\t\tdata-slot=\"code-block\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-mono w-full overflow-hidden rounded-md border border-gray-300 bg-card font-mono\",\n\t\t\t\t\t\"[&_svg]:shrink-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\n\t\treturn (\n\t\t\t<CodeBlockContext.Provider value={context}>\n\t\t\t\t{hasTabs ? (\n\t\t\t\t\t<RadixTabsRoot\n\t\t\t\t\t\tasChild\n\t\t\t\t\t\tdefaultValue={defaultTab}\n\t\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\t\tonValueChange={onActiveTabChange}\n\t\t\t\t\t>\n\t\t\t\t\t\t{tree}\n\t\t\t\t\t</RadixTabsRoot>\n\t\t\t\t) : (\n\t\t\t\t\ttree\n\t\t\t\t)}\n\t\t\t</CodeBlockContext.Provider>\n\t\t);\n\t},\n);\nRoot.displayName = \"CodeBlock\";\n\n/**\n * The body of the `CodeBlock`. This is where `CodeBlock.Code` and\n * the optional `CodeBlock.CopyButton` are rendered.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * </CodeBlock.Root>\n * ```\n */\nconst Body = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild = false, className, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\t\treturn <Component className={cx(\"relative\", className)} ref={ref} {...props} />;\n\t},\n);\nBody.displayName = \"CodeBlockBody\";\n\n/**\n * Matches `SHIKI_VAL_<index>` placeholders injected by the Vite plugin for\n * interpolated template expressions. Hoisted to module scope to avoid\n * re-creating the regex on every substitution call.\n */\nconst LEGACY_SHIKI_VAL_PATTERN = /SHIKI_VAL_(\\d+)/g;\n\n/** Escapes special characters in a string for use in a `RegExp` constructor. */\nfunction escapeForRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst maxPreValPatternCacheSize = 500;\nconst preValPatternCache = new Map<string, RegExp>();\n\n/**\n * Returns the cached `RegExp` for the given `preValToken`, falling back to the\n * legacy `SHIKI_VAL_<n>` pattern when no token is provided.\n */\nfunction getTemplateValPattern(preValToken: string | undefined): RegExp {\n\tif (preValToken == null || preValToken.length === 0) {\n\t\treturn LEGACY_SHIKI_VAL_PATTERN;\n\t}\n\n\tlet cached = preValPatternCache.get(preValToken);\n\tif (cached == null) {\n\t\tif (preValPatternCache.size >= maxPreValPatternCacheSize) {\n\t\t\tpreValPatternCache.clear();\n\t\t}\n\t\tcached = new RegExp(`${escapeForRegExp(preValToken)}(\\\\d+)__`, \"g\");\n\t\tpreValPatternCache.set(preValToken, cached);\n\t}\n\treturn cached;\n}\n\n/**\n * Replaces placeholder tokens in `input` with values from `vals`, applying\n * `mapValue` to each substituted value. Returns the input unchanged when\n * no placeholders are present.\n */\nfunction substituteTemplateVals(\n\tinput: string,\n\tvals: unknown[],\n\tpreValToken: string | undefined,\n\tmapValue: (value: unknown) => string,\n): string {\n\tif (preValToken == null) {\n\t\tif (!input.includes(\"SHIKI_VAL_\")) {\n\t\t\treturn input;\n\t\t}\n\t} else if (!input.includes(preValToken)) {\n\t\treturn input;\n\t}\n\n\treturn input.replaceAll(getTemplateValPattern(preValToken), (match, indexText: string) => {\n\t\tconst index = Number.parseInt(indexText, 10);\n\t\tif (Number.isNaN(index) || index < 0 || index >= vals.length) {\n\t\t\treturn match;\n\t\t}\n\t\treturn mapValue(vals[index]);\n\t});\n}\n\n/** Substitutes placeholder tokens in pre-rendered HTML, HTML-escaping each interpolated value. */\nfunction substitutePreVals(html: string, vals: unknown[], preValToken: string | undefined): string {\n\treturn substituteTemplateVals(html, vals, preValToken, (value) => escapeHtml(String(value)));\n}\n\n/** Substitutes placeholder tokens in plain text (for the copy button), without HTML escaping. */\nfunction substitutePreValsPlainText(\n\ttext: string,\n\tvals: unknown[],\n\tpreValToken: string | undefined,\n): string {\n\treturn substituteTemplateVals(text, vals, preValToken, (value) => String(value));\n}\n\ntype CodeBlockCodeProps = Omit<ComponentProps<\"pre\">, \"children\"> & {\n\t/**\n\t * The code value produced by `mantleCode(\"lang\")` tagged template.\n\t * Contains pre-rendered Shiki HTML (when the Vite plugin is active) and\n\t * the original code string for the copy button.\n\t */\n\tvalue: MantleCodeBlockValue;\n};\n\n/**\n * The `CodeBlock` content. Renders pre-highlighted code from `mantleCode()`.\n *\n * `value[\"~preHtml\"]` must be provided by Mantle's Vite plugin or server highlighter.\n * Runtime highlighting and runtime line decoration are intentionally unsupported.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * ```\n */\nconst Code = forwardRef<ComponentRef<\"pre\">, CodeBlockCodeProps>(\n\t({ className, style, tabIndex, value, ...props }, ref) => {\n\t\tconst id = useId();\n\t\tconst { copyTextRef, hasCodeExpander, isCodeExpanded, registerCodeId, unregisterCodeId } =\n\t\t\tuseCodeBlockContext();\n\t\tconst {\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\t\"~preValToken\": __preValToken,\n\t\t\t\"~preVals\": __preVals,\n\t\t\t\"~highlightLines\": __highlightLines,\n\t\t\t\"~lineNumberStart\": __lineNumberStart,\n\t\t\t\"~preHtml\": __preHtml,\n\t\t\t\"~showLineNumbers\": __showLineNumbers,\n\t\t} = value;\n\n\t\tconst effectiveHighlightLines = __highlightLines;\n\t\tconst effectiveLineNumberStart = __lineNumberStart ?? 1;\n\t\tconst effectiveShowLineNumbers = __showLineNumbers ?? false;\n\t\tconst copyText = useMemo(\n\t\t\t() =>\n\t\t\t\t__preVals != null && __preVals.length > 0\n\t\t\t\t\t? substitutePreValsPlainText(code, __preVals, __preValToken)\n\t\t\t\t\t: code,\n\t\t\t[__preValToken, __preVals, code],\n\t\t);\n\n\t\tuseLayoutEffect(() => {\n\t\t\tcopyTextRef.current = copyText;\n\t\t}, [copyTextRef, copyText]);\n\n\t\tuseEffect(() => {\n\t\t\tregisterCodeId(id);\n\n\t\t\treturn () => {\n\t\t\t\tunregisterCodeId(id);\n\t\t\t};\n\t\t}, [id, registerCodeId, unregisterCodeId]);\n\n\t\tconst renderedHtml = useMemo(() => {\n\t\t\tif (__preHtml == null) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn __preVals != null && __preVals.length > 0\n\t\t\t\t? substitutePreVals(__preHtml, __preVals, __preValToken)\n\t\t\t\t: __preHtml;\n\t\t}, [__preHtml, __preValToken, __preVals]);\n\n\t\tconst isPreRendered = renderedHtml != null;\n\t\tconst displayHtml = renderedHtml ?? escapeHtml(copyText);\n\n\t\treturn (\n\t\t\t<pre\n\t\t\t\taria-expanded={hasCodeExpander ? isCodeExpanded : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"scrollbar overflow-x-auto overflow-y-hidden py-4\",\n\t\t\t\t\t!isPreRendered && \"pr-14\",\n\t\t\t\t\t\"data-[mantle-line-numbers~='false']:pl-4\",\n\t\t\t\t\t\"text-mono m-0 font-mono\",\n\t\t\t\t\t\"aria-collapsed:max-h-[13.6rem]\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-highlighted={isPreRendered ? \"true\" : \"false\"}\n\t\t\t\tdata-lang={language}\n\t\t\t\tdata-mantle-highlight-lines={\n\t\t\t\t\tisPreRendered && effectiveHighlightLines != null && effectiveHighlightLines.length > 0\n\t\t\t\t\t\t? effectiveHighlightLines.join(\",\")\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-mantle-line-number-start={\n\t\t\t\t\tisPreRendered && effectiveShowLineNumbers ? String(effectiveLineNumberStart) : \"1\"\n\t\t\t\t}\n\t\t\t\tdata-mantle-line-numbers={isPreRendered && effectiveShowLineNumbers ? \"true\" : \"false\"}\n\t\t\t\tid={id}\n\t\t\t\tref={ref}\n\t\t\t\tstyle={\n\t\t\t\t\t{\n\t\t\t\t\t\t...style,\n\t\t\t\t\t\t\"--mantle-line-number-start\": String(effectiveLineNumberStart),\n\t\t\t\t\t\ttabSize: 2,\n\t\t\t\t\t\tMozTabSize: 2,\n\t\t\t\t\t} as ComponentProps<\"pre\">[\"style\"]\n\t\t\t\t}\n\t\t\t\ttabIndex={tabIndex ?? -1}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<code\n\t\t\t\t\tclassName=\"text-size-inherit block min-w-full w-max\"\n\t\t\t\t\tdangerouslySetInnerHTML={{ __html: displayHtml }}\n\t\t\t\t/>\n\t\t\t</pre>\n\t\t);\n\t},\n);\nCode.displayName = \"CodeBlockCode\";\n\n/**\n * The (optional) header slot of the `CodeBlock`. This is where\n * `CodeBlock.Icon` and `CodeBlock.Title` are rendered.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * </CodeBlock.Root>\n * ```\n */\nconst Header = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild = false, className, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"flex items-center gap-1 border-b border-gray-300 bg-base px-4 py-2 text-gray-700\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nHeader.displayName = \"CodeBlockHeader\";\n\n/**\n * The (optional) title of the `CodeBlock`. Renders as `h3` by default;\n * use `asChild` to render a different element.\n *\n * @example\n * ```tsx\n * <CodeBlock.Header>\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * ```\n */\nconst Title = forwardRef<\n\tHTMLHeadingElement,\n\tHTMLAttributes<HTMLHeadingElement> & { asChild?: boolean }\n>(({ asChild = false, className, ...props }, ref) => {\n\tconst Component = asChild ? Slot : \"h3\";\n\treturn (\n\t\t<Component\n\t\t\tref={ref}\n\t\t\tclassName={cx(\"text-mono m-0 font-mono font-normal\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nTitle.displayName = \"CodeBlockTitle\";\n\ntype CodeBlockCopyButtonProps = Omit<ComponentProps<\"button\">, \"children\" | \"type\"> & {\n\t/**\n\t * Callback fired when the copy button is clicked, passes the copied text as an argument.\n\t */\n\tonCopy?: (value: string) => void;\n\t/**\n\t * Callback fired when an error occurs during copying.\n\t */\n\tonCopyError?: (error: unknown) => void;\n};\n\n/**\n * The (optional) copy button of the `CodeBlock`. Copies the code content\n * to the clipboard when clicked.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`…`} />\n * </CodeBlock.Body>\n * ```\n */\nconst CopyButton = forwardRef<ComponentRef<\"button\">, CodeBlockCopyButtonProps>(\n\t({ className, onCopy, onCopyError, onClick, ...props }, ref) => {\n\t\tconst { copyTextRef } = useCodeBlockContext();\n\t\tconst [, copyToClipboard] = useCopyToClipboard();\n\t\tconst [wasCopied, setWasCopied] = useState(false);\n\t\tconst timeoutHandle = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n\t\tuseEffect(() => {\n\t\t\treturn () => {\n\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t}\n\t\t\t};\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<span className=\"absolute right-2.5 top-2.5 z-10 bg-card\">\n\t\t\t\t<IconButton\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tlabel=\"Copy code\"\n\t\t\t\t\ticon={wasCopied ? <CheckIcon /> : <CopyIcon />}\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tref={ref}\n\t\t\t\t\tonClick={async (event) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tonClick?.(event);\n\t\t\t\t\t\t\tif (event.defaultPrevented) {\n\t\t\t\t\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst text = copyTextRef.current;\n\t\t\t\t\t\t\tawait copyToClipboard(text);\n\t\t\t\t\t\t\tonCopy?.(text);\n\t\t\t\t\t\t\tsetWasCopied(true);\n\t\t\t\t\t\t\tif (timeoutHandle.current != null) {\n\t\t\t\t\t\t\t\tclearTimeout(timeoutHandle.current);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimeoutHandle.current = setTimeout(() => {\n\t\t\t\t\t\t\t\tsetWasCopied(false);\n\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tonCopyError?.(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t</span>\n\t\t);\n\t},\n);\nCopyButton.displayName = \"CodeBlockCopyButton\";\n\ntype CodeBlockExpanderButtonProps = Omit<\n\tComponentProps<\"button\">,\n\t\"children\" | \"aria-controls\" | \"aria-expanded\"\n> &\n\tWithAsChild;\n\n/**\n * The (optional) expander button of the `CodeBlock`. Toggles the expanded\n * state of the code block. When present, the code block is collapsible.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Body>\n * <CodeBlock.Code value={mantleCode(\"typescript\")`…`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n * ```\n */\nconst ExpanderButton = forwardRef<ComponentRef<\"button\">, CodeBlockExpanderButtonProps>(\n\t({ asChild = false, className, onClick, ...props }, ref) => {\n\t\tconst { codeId, isCodeExpanded, setIsCodeExpanded, setHasCodeExpander } = useCodeBlockContext();\n\n\t\tuseEffect(() => {\n\t\t\tsetHasCodeExpander(true);\n\t\t\treturn () => {\n\t\t\t\tsetHasCodeExpander(false);\n\t\t\t};\n\t\t}, [setHasCodeExpander]);\n\n\t\tconst Component = asChild ? Slot : \"button\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\t{...props}\n\t\t\t\taria-controls={codeId}\n\t\t\t\taria-expanded={isCodeExpanded}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"flex w-full items-center justify-center gap-0.5 border-t border-gray-300 bg-card px-4 py-2 font-sans text-gray-700 hover:bg-gray-100\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\tsetIsCodeExpanded((prev) => !prev);\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{isCodeExpanded ? \"Show less\" : \"Show more\"}{\" \"}\n\t\t\t\t<MantleIcon\n\t\t\t\t\tsvg={<CaretDownIcon weight=\"bold\" />}\n\t\t\t\t\tclassName={cx(\"size-4\", isCodeExpanded && \"rotate-180\", \"transition-all duration-150\")}\n\t\t\t\t/>\n\t\t\t</Component>\n\t\t);\n\t},\n);\nExpanderButton.displayName = \"CodeBlockExpanderButton\";\n\ntype CodeBlockIconProps = Omit<SvgAttributes, \"children\"> &\n\t(\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * A custom icon SVG to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tsvg: ReactNode;\n\t\t\t\t/**\n\t\t\t\t * A preset icon to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tpreset?: undefined | never;\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * A custom icon SVG to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tsvg?: undefined | never;\n\t\t\t\t/**\n\t\t\t\t * A preset icon to display in the code block header.\n\t\t\t\t * (Pass only one of `svg` or `preset`.)\n\t\t\t\t */\n\t\t\t\tpreset: Mode;\n\t\t }\n\t);\n\n/**\n * A small icon for the `CodeBlock` header. Pass either a custom `svg`\n * or a `preset` value (not both).\n *\n * @example\n * ```tsx\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * ```\n */\nfunction CodeBlockIconComponent({\n\tclassName,\n\tpreset,\n\tsvg: _svgProp,\n\t...props\n}: CodeBlockIconProps) {\n\tlet svg = _svgProp;\n\tif (preset != null) {\n\t\tswitch (preset) {\n\t\t\tcase \"file\":\n\t\t\t\tsvg = <FileTextIcon weight=\"fill\" />;\n\t\t\t\tbreak;\n\t\t\tcase \"cli\":\n\t\t\t\tsvg = <TerminalIcon weight=\"fill\" />;\n\t\t\t\tbreak;\n\t\t\tcase \"traffic-policy\":\n\t\t\t\tsvg = <TrafficPolicyFileIcon />;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn <MantleIcon className={className} svg={svg} {...props} />;\n}\nCodeBlockIconComponent.displayName = \"CodeBlockIcon\";\n\ntype CodeBlockTabListProps = Omit<ComponentProps<typeof RadixTabsList>, \"asChild\" | \"loop\">;\n\n/**\n * A tab list for the `CodeBlock` header. Renders pill-styled tab triggers\n * that switch which code is displayed. Built on Radix Tabs primitives.\n *\n * Place this inside `CodeBlock.Header` and pair with `CodeBlock.TabContent`\n * in `CodeBlock.Body` to conditionally render code based on the active tab.\n * Tab state is managed by `CodeBlock.Root` via `defaultTab` / `activeTab` / `onActiveTabChange`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root defaultTab=\"yml\">\n * <CodeBlock.Header>\n * <CodeBlock.TabList>\n * <CodeBlock.TabTrigger value=\"yml\">policy.yml</CodeBlock.TabTrigger>\n * <CodeBlock.TabTrigger value=\"json\">policy.json</CodeBlock.TabTrigger>\n * </CodeBlock.TabList>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.TabContent value=\"yml\">\n * <CodeBlock.Code value={ymlValue} />\n * </CodeBlock.TabContent>\n * <CodeBlock.TabContent value=\"json\">\n * <CodeBlock.Code value={jsonValue} />\n * </CodeBlock.TabContent>\n * </CodeBlock.Body>\n * </CodeBlock.Root>\n * ```\n */\nconst TabList = forwardRef<ComponentRef<typeof RadixTabsList>, CodeBlockTabListProps>(\n\t({ className, ...props }, ref) => (\n\t\t<RadixTabsList className={cx(\"flex items-center gap-1\", className)} ref={ref} {...props} />\n\t),\n);\nTabList.displayName = \"CodeBlockTabList\";\n\ntype CodeBlockTabTriggerProps = Omit<ComponentProps<typeof RadixTabsTrigger>, \"asChild\">;\n\n/**\n * A pill-styled tab trigger for the `CodeBlock` header.\n * Must be rendered within a `CodeBlock.TabList`.\n *\n * @example\n * ```tsx\n * <CodeBlock.TabList>\n * <CodeBlock.TabTrigger value=\"yml\">policy.yml</CodeBlock.TabTrigger>\n * <CodeBlock.TabTrigger value=\"json\">policy.json</CodeBlock.TabTrigger>\n * </CodeBlock.TabList>\n * ```\n */\nconst TabTrigger = forwardRef<ComponentRef<typeof RadixTabsTrigger>, CodeBlockTabTriggerProps>(\n\t({ className, ...props }, ref) => (\n\t\t<RadixTabsTrigger\n\t\t\tclassName={cx(\n\t\t\t\t\"cursor-pointer rounded px-1.5 py-0.5 text-xs font-medium\",\n\t\t\t\t\"text-gray-600 outline-hidden\",\n\t\t\t\t\"hover:text-gray-900\",\n\t\t\t\t\"data-[state=active]:bg-neutral-500/15 data-[state=active]:text-strong\",\n\t\t\t\t\"focus-visible:ring-focus-accent focus-visible:ring-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nTabTrigger.displayName = \"CodeBlockTabTrigger\";\n\ntype CodeBlockTabContentProps = Omit<\n\tComponentProps<typeof RadixTabsContent>,\n\t\"asChild\" | \"forceMount\"\n>;\n\n/**\n * Conditionally renders its children when the associated tab is active.\n * Pair with `CodeBlock.TabList` and `CodeBlock.TabTrigger` in the header,\n * and set `defaultTab` / `activeTab` on `CodeBlock.Root`.\n *\n * @example\n * ```tsx\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.TabContent value=\"yml\">\n * <CodeBlock.Code value={ymlValue} />\n * </CodeBlock.TabContent>\n * <CodeBlock.TabContent value=\"json\">\n * <CodeBlock.Code value={jsonValue} />\n * </CodeBlock.TabContent>\n * </CodeBlock.Body>\n * ```\n */\nconst TabContent = forwardRef<ComponentRef<typeof RadixTabsContent>, CodeBlockTabContentProps>(\n\t(props, ref) => <RadixTabsContent ref={ref} {...props} />,\n);\nTabContent.displayName = \"CodeBlockTabContent\";\n\n/**\n * Shiki-powered code blocks with build-time syntax highlighting and zero browser bundle.\n *\n * Use `mantleCodeBlockPlugins()` to enable pre-rendering at build time.\n *\n * @example\n * ```tsx\n * <CodeBlock.Root>\n * <CodeBlock.Header>\n * <CodeBlock.Icon preset=\"file\" />\n * <CodeBlock.Title>example.ts</CodeBlock.Title>\n * </CodeBlock.Header>\n * <CodeBlock.Body>\n * <CodeBlock.CopyButton />\n * <CodeBlock.Code value={mantleCode(\"typescript\")`const x = \"hello\";`} />\n * </CodeBlock.Body>\n * <CodeBlock.ExpanderButton />\n * </CodeBlock.Root>\n *\n * // Server-highlighted HTML fetched via an action route + React Query mutation\n * const highlightMutation = useMutation({\n * mutationFn: async () => {\n * const response = await fetch(\"/api/shiki-highlight\", {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({ code: source, language: \"typescript\" }),\n * });\n * return response.json();\n * },\n * });\n *\n * const serverValue = createMantleCodeBlockValue({\n * language: \"typescript\",\n * code: source,\n * preHtml: highlightMutation.data?.html,\n * });\n * ```\n */\nconst CodeBlock = {\n\t/**\n\t * The root component of the `CodeBlock`.\n\t */\n\tRoot,\n\t/**\n\t * The body of the `CodeBlock`. Contains `Code` and optional `CopyButton`.\n\t */\n\tBody,\n\t/**\n\t * The code content. Renders pre-highlighted Shiki HTML when the Vite plugin is active.\n\t */\n\tCode,\n\t/**\n\t * The optional copy button.\n\t */\n\tCopyButton,\n\t/**\n\t * The optional expander button for collapsible code blocks.\n\t */\n\tExpanderButton,\n\t/**\n\t * The optional header slot for icon and title.\n\t */\n\tHeader,\n\t/**\n\t * A small icon for the code block header. Use `preset` or `svg`.\n\t */\n\tIcon: CodeBlockIconComponent,\n\t/**\n\t * Conditionally renders children when the associated tab is active.\n\t */\n\tTabContent,\n\t/**\n\t * A tab list for the code block header. Renders pill-styled tabs for switching code.\n\t */\n\tTabList,\n\t/**\n\t * A pill-styled tab trigger for the code block header. Must be inside `TabList`.\n\t */\n\tTabTrigger,\n\t/**\n\t * The optional title rendered in the header.\n\t */\n\tTitle,\n} as const;\n\nexport {\n\t//,\n\tCodeBlock,\n};\n","/**\n * Returns `true` if `value` has more than `maxLines` newline-delimited lines.\n *\n * This is equivalent to `value.split(\"\\\\n\").length > maxLines`, but avoids\n * allocating an intermediate array and can early-return once the threshold is exceeded.\n */\nfunction hasMoreThanNLines(value: string, maxLines: number): boolean {\n\tlet lines = 1;\n\tif (lines > maxLines) {\n\t\treturn true;\n\t}\n\n\tfor (let i = 0; i < value.length; i++) {\n\t\tif (value[i] === \"\\n\") {\n\t\t\tlines += 1;\n\t\t\tif (lines > maxLines) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nexport {\n\t//,\n\thasMoreThanNLines,\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { C as parseLanguage, D as LineRange, E as decorateHighlightedHtml, S as isSupportedLanguage, T as DecorateHighlightedHtmlInput, _ as normalizeIndentation, b as isIndentation, g as parseCodeBlockShowLineNumbers, h as parseCodeBlockLineNumberStart, m as parseCodeBlockHighlightLines, p as tokenizeMetastring, u as normalizeValue, v as Indentation, w as supportedLanguages, x as SupportedLanguage, y as inferIndentation } from "./resolve-pre-rendered-props-51i50IL2.js";
2
- export { type DecorateHighlightedHtmlInput, type Indentation, type LineRange, type SupportedLanguage, decorateHighlightedHtml, inferIndentation, isIndentation, isSupportedLanguage, normalizeIndentation, normalizeValue, parseCodeBlockHighlightLines, parseCodeBlockLineNumberStart, parseCodeBlockShowLineNumbers, parseLanguage, supportedLanguages, tokenizeMetastring };
1
+ import { A as DecorateHighlightedHtmlInput, C as Indentation, D as isSupportedLanguage, E as SupportedLanguage, M as LineRange, O as parseLanguage, S as normalizeIndentation, T as isIndentation, b as defaultShowLineNumbers, g as parseCodeBlockShowLineNumbers, h as parseCodeBlockLineNumberStart, j as decorateHighlightedHtml, k as supportedLanguages, m as parseCodeBlockHighlightLines, p as tokenizeMetastring, u as normalizeValue, w as inferIndentation } from "./resolve-pre-rendered-props-B3YDbOFZ.js";
2
+ export { type DecorateHighlightedHtmlInput, type Indentation, type LineRange, type SupportedLanguage, decorateHighlightedHtml, defaultShowLineNumbers, inferIndentation, isIndentation, isSupportedLanguage, normalizeIndentation, normalizeValue, parseCodeBlockHighlightLines, parseCodeBlockLineNumberStart, parseCodeBlockShowLineNumbers, parseLanguage, supportedLanguages, tokenizeMetastring };
@@ -1 +1 @@
1
- import{a as e,c as t,d as n,f as r,h as i,l as a,m as o,n as s,o as c,p as l,s as u,u as d}from"./resolve-pre-rendered-props-Bu2cvS9A.js";export{i as decorateHighlightedHtml,l as inferIndentation,o as isIndentation,a as isSupportedLanguage,r as normalizeIndentation,s as normalizeValue,c as parseCodeBlockHighlightLines,u as parseCodeBlockLineNumberStart,t as parseCodeBlockShowLineNumbers,d as parseLanguage,n as supportedLanguages,e as tokenizeMetastring};
1
+ import{_ as e,a as t,c as n,d as r,f as i,h as a,l as o,m as s,n as c,o as l,p as u,s as d,u as f}from"./resolve-pre-rendered-props--3gLTSwE.js";export{a as decorateHighlightedHtml,e as defaultShowLineNumbers,u as inferIndentation,s as isIndentation,o as isSupportedLanguage,i as normalizeIndentation,c as normalizeValue,l as parseCodeBlockHighlightLines,d as parseCodeBlockLineNumberStart,n as parseCodeBlockShowLineNumbers,f as parseLanguage,r as supportedLanguages,t as tokenizeMetastring};
package/dist/command.d.ts CHANGED
@@ -178,7 +178,7 @@ declare const Command: {
178
178
  ref?: React.Ref<HTMLInputElement>;
179
179
  } & {
180
180
  asChild?: boolean;
181
- }, "key" | "asChild" | keyof _$react.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "value" | "type"> & {
181
+ }, "key" | keyof _$react.InputHTMLAttributes<HTMLInputElement> | "asChild">, "value" | "onChange" | "type"> & {
182
182
  value?: string;
183
183
  onValueChange?: (search: string) => void;
184
184
  } & _$react.RefAttributes<HTMLInputElement>, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
@@ -262,7 +262,7 @@ declare const Command: {
262
262
  ref?: React.Ref<HTMLDivElement>;
263
263
  } & {
264
264
  asChild?: boolean;
265
- }, "key" | keyof _$react.HTMLAttributes<HTMLDivElement> | "asChild">, "disabled" | "onSelect" | "value"> & {
265
+ }, "key" | keyof _$react.HTMLAttributes<HTMLDivElement> | "asChild">, "disabled" | "value" | "onSelect"> & {
266
266
  disabled?: boolean;
267
267
  onSelect?: (value: string) => void;
268
268
  value?: string;
@@ -1,4 +1,4 @@
1
- import { t as Button } from "./button-BaNwe1ud.js";
1
+ import { t as Button } from "./button-CX98GGHD.js";
2
2
  import { s as SortingMode } from "./direction-MVSxfKWx.js";
3
3
  import { t as Table$1 } from "./table-C7BejaFW.js";
4
4
  import * as _$react from "react";
@@ -158,6 +158,31 @@ declare function ActionCell({
158
158
  declare namespace ActionCell {
159
159
  var displayName: string;
160
160
  }
161
+ type DataTableActionHeaderProps = ComponentProps<typeof Table$1.Header>;
162
+ /**
163
+ * A sticky header cell that pairs with `DataTable.ActionCell`. Use this as the
164
+ * header for the action column so the pinned column visually aligns across the
165
+ * header and every body row when the table scrolls horizontally.
166
+ *
167
+ * @see https://mantle.ngrok.com/components/data-table#datatableactionheader
168
+ *
169
+ * @example
170
+ * ```tsx
171
+ * columnHelper.display({
172
+ * id: "actions",
173
+ * header: () => <DataTable.ActionHeader />,
174
+ * cell: () => <DataTable.ActionCell>{...}</DataTable.ActionCell>,
175
+ * })
176
+ * ```
177
+ */
178
+ declare function ActionHeader({
179
+ children,
180
+ className,
181
+ ...props
182
+ }: DataTableActionHeaderProps): _$react_jsx_runtime0.JSX.Element;
183
+ declare namespace ActionHeader {
184
+ var displayName: string;
185
+ }
161
186
  /**
162
187
  * A data table component that provides sorting and other data table functionality.
163
188
  * Built on top of TanStack Table for advanced table features.
@@ -205,6 +230,22 @@ declare const DataTable: {
205
230
  * ```
206
231
  */
207
232
  readonly ActionCell: typeof ActionCell;
233
+ /**
234
+ * A sticky header cell that pairs with `DataTable.ActionCell`, keeping the
235
+ * action column aligned across the header and body when scrolling horizontally.
236
+ *
237
+ * @see https://mantle.ngrok.com/components/data-table#datatableactionheader
238
+ *
239
+ * @example
240
+ * ```tsx
241
+ * columnHelper.display({
242
+ * id: "actions",
243
+ * header: () => <DataTable.ActionHeader />,
244
+ * cell: () => <DataTable.ActionCell>{...}</DataTable.ActionCell>,
245
+ * })
246
+ * ```
247
+ */
248
+ readonly ActionHeader: typeof ActionHeader;
208
249
  /**
209
250
  * A table cell component for rendering individual data cells.
210
251
  *
@@ -1,2 +1,2 @@
1
- import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./button-BKykcpgJ.js";import{i as n}from"./direction-Ca88oQhP.js";import{t as r}from"./sort-mo52clyh.js";import{t as i}from"./table-CnYWz6IT.js";import{Fragment as a,createContext as o,useContext as s,useMemo as c}from"react";import l from"tiny-invariant";import{jsx as u,jsxs as d}from"react/jsx-runtime";import{flexRender as f}from"@tanstack/react-table";export*from"@tanstack/react-table";const p=[`unsorted`,`asc`,`desc`],m=[`unsorted`,`desc`,`asc`];function h(e,t){return g(t===`alphanumeric`?p:m,e)??`unsorted`}function g(e,t,n){if(e.length===0)return n;let r=e.findIndex(e=>e===t);if(r===-1)return n;let i=(r+1)%e.length;return e.at(i)??n}const _=o(null);function v(){let e=s(_);return l(e,`useDataTableContext should only be used within a DataTable child component`),e}function y({children:e,table:t,...n}){let r=c(()=>({table:t}),[t]);return u(_.Provider,{value:r,children:u(i.Root,{...n,children:u(i.Element,{children:e})})})}function b({children:r,className:i,column:a,disableSorting:o=!1,iconPlacement:s=`end`,sortingMode:c,sortIcon:l,onClick:f,...p}){let m=a.getIsSorted(),h=!o&&a.getCanSort(),g=h&&typeof m==`string`?m:`unsorted`,_=l?.(g)??u(O,{mode:c,direction:g});return d(t,{appearance:`ghost`,className:e(`flex justify-start w-full h-full rounded-none not-disabled:active:scale-none text-muted`,i),"data-sort-direction":g,"data-table-header-action":!0,icon:_,iconPlacement:s,onClick:e=>{f?.(e),!e.defaultPrevented&&(!h||o||c===void 0||k(a,c))},priority:`neutral`,type:`button`,...p,children:[h&&g!==`unsorted`&&d(`span`,{className:`sr-only`,children:[`Column sorted in`,` `,c===`alphanumeric`?g===`asc`?`ascending`:`descending`:n(g),` `,`order`]}),r]})}function x({children:t,className:n,...r}){return u(i.Header,{className:e(`has-data-table-header-action:px-0`,n),...r,children:t})}const S=i.Body;S.displayName=`DataTableBody`;function C(e){let{table:t}=v();return u(i.Head,{...e,children:t.getHeaderGroups().map(e=>u(i.Row,{children:e.headers.map(e=>u(a,{children:e.isPlaceholder?u(i.Header,{},e.id):f(e.column.columnDef.header,e.getContext())},e.id))},e.id))})}function w({row:e,...t}){return u(i.Row,{...t,children:e.getVisibleCells().map(e=>u(a,{children:f(e.column.columnDef.cell,e.getContext())},e.id))})}function T({children:e,...t}){let{table:n}=v(),r=n.getAllColumns().length;return u(i.Row,{...t,children:u(i.Cell,{colSpan:r,children:e})})}function E({children:t,className:n,...r}){return u(i.Cell,{className:e(`sticky z-10 right-0 top-px -bottom-px flex items-center justify-end p-2 group-data-sticky-active/table:[box-shadow:inset_10px_0_8px_-8px_oklch(0_0_0/15%)]`,n),...r,children:t})}y.displayName=`DataTable`,E.displayName=`DataTableActionCell`,S.displayName=`DataTableBody`,T.displayName=`DataTableEmptyRow`,C.displayName=`DataTableHead`,x.displayName=`DataTableHeader`,b.displayName=`DataTableHeaderSortButton`,w.displayName=`DataTableRow`;const D={Root:y,ActionCell:E,Cell:i.Cell,Body:S,EmptyRow:T,Head:C,Header:x,HeaderSortButton:b,Row:w};function O({direction:e,mode:t,...n}){return e===`unsorted`||!t||!e?u(`svg`,{"aria-hidden":!0,...n}):u(r,{mode:t,direction:e,...n})}function k(e,t){if(!e.getCanSort())return;let n=e.getIsSorted();switch(h(typeof n==`string`?n:`unsorted`,t)){case`unsorted`:e.clearSorting();return;case`asc`:e.toggleSorting(!1);return;case`desc`:e.toggleSorting(!0);return;default:return}}export{D as DataTable};
1
+ import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./button-BKykcpgJ.js";import{i as n}from"./direction-Ca88oQhP.js";import{t as r}from"./sort-mo52clyh.js";import{t as i}from"./table-DDeUXBex.js";import{Fragment as a,createContext as o,useContext as s,useMemo as c}from"react";import l from"tiny-invariant";import{jsx as u,jsxs as d}from"react/jsx-runtime";import{flexRender as f}from"@tanstack/react-table";export*from"@tanstack/react-table";const p=[`unsorted`,`asc`,`desc`],m=[`unsorted`,`desc`,`asc`];function h(e,t){return g(t===`alphanumeric`?p:m,e)??`unsorted`}function g(e,t,n){if(e.length===0)return n;let r=e.findIndex(e=>e===t);if(r===-1)return n;let i=(r+1)%e.length;return e.at(i)??n}const _=o(null);function v(){let e=s(_);return l(e,`useDataTableContext should only be used within a DataTable child component`),e}function y({children:e,table:t,...n}){let r=c(()=>({table:t}),[t]);return u(_.Provider,{value:r,children:u(i.Root,{...n,children:u(i.Element,{children:e})})})}function b({children:r,className:i,column:a,disableSorting:o=!1,iconPlacement:s=`end`,sortingMode:c,sortIcon:l,onClick:f,...p}){let m=a.getIsSorted(),h=!o&&a.getCanSort(),g=h&&typeof m==`string`?m:`unsorted`,_=l?.(g)??u(A,{mode:c,direction:g});return d(t,{appearance:`ghost`,className:e(`flex justify-start w-full h-full rounded-none not-disabled:active:scale-none text-muted`,i),"data-sort-direction":g,"data-table-header-action":!0,icon:_,iconPlacement:s,onClick:e=>{f?.(e),!e.defaultPrevented&&(!h||o||c===void 0||j(a,c))},priority:`neutral`,type:`button`,...p,children:[h&&g!==`unsorted`&&d(`span`,{className:`sr-only`,children:[`Column sorted in`,` `,c===`alphanumeric`?g===`asc`?`ascending`:`descending`:n(g),` `,`order`]}),r]})}function x({children:t,className:n,...r}){return u(i.Header,{className:e(`has-data-table-header-action:px-0`,n),...r,children:t})}const S=i.Body;S.displayName=`DataTableBody`;function C(e){let{table:t}=v();return u(i.Head,{...e,children:t.getHeaderGroups().map(e=>u(i.Row,{children:e.headers.map(e=>u(a,{children:e.isPlaceholder?u(i.Header,{},e.id):f(e.column.columnDef.header,e.getContext())},e.id))},e.id))})}function w({row:e,...t}){return u(i.Row,{...t,children:e.getVisibleCells().map(e=>u(a,{children:f(e.column.columnDef.cell,e.getContext())},e.id))})}function T({children:e,...t}){let{table:n}=v(),r=n.getAllColumns().length;return u(i.Row,{...t,children:u(i.Cell,{colSpan:r,children:e})})}function E(){return u(`span`,{"aria-hidden":!0,className:e(`pointer-events-none absolute -inset-y-px -left-1.5 w-1.5`,`opacity-0 transition-opacity group-data-sticky-active/table:opacity-100`,`shadow-[1px_0_0_0_var(--border-color-card-muted)]`,`bg-linear-to-l to-transparent`,`from-[color-mix(in_oklab,var(--shadow-color)_var(--shadow-second-opacity),transparent)]`)})}function D({children:t,className:n,...r}){return d(i.Cell,{"data-mantle-table-sticky-right":!0,className:e(`sticky z-10 right-0 flex items-center justify-end bg-inherit p-2`,n),...r,children:[u(E,{}),t]})}function O({children:t,className:n,...r}){let{table:a}=v(),o=a.getRowModel().rows.length>0;return d(i.Header,{...o?{"data-mantle-table-sticky-right":!0}:{},className:e(o&&`sticky z-10 right-0 bg-inherit`,n),...r,children:[o&&u(E,{}),t]})}y.displayName=`DataTable`,D.displayName=`DataTableActionCell`,O.displayName=`DataTableActionHeader`,S.displayName=`DataTableBody`,T.displayName=`DataTableEmptyRow`,C.displayName=`DataTableHead`,x.displayName=`DataTableHeader`,b.displayName=`DataTableHeaderSortButton`,w.displayName=`DataTableRow`;const k={Root:y,ActionCell:D,ActionHeader:O,Cell:i.Cell,Body:S,EmptyRow:T,Head:C,Header:x,HeaderSortButton:b,Row:w};function A({direction:e,mode:t,...n}){return e===`unsorted`||!t||!e?u(`svg`,{"aria-hidden":!0,...n}):u(r,{mode:t,direction:e,...n})}function j(e,t){if(!e.getCanSort())return;let n=e.getIsSorted();switch(h(typeof n==`string`?n:`unsorted`,t)){case`unsorted`:e.clearSorting();return;case`asc`:e.toggleSorting(!1);return;case`desc`:e.toggleSorting(!0);return;default:return}}export{k as DataTable};
2
2
  //# sourceMappingURL=data-table.js.map