@traefik-labs/faency 12.1.0 → 12.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,12 +12,13 @@ const Button_vanilla = require("../Button/Button.vanilla.cjs");
12
12
  const AccessibleIcon = require("../AccessibleIcon/AccessibleIcon.cjs");
13
13
  const CodeBlockVanilla = React.forwardRef(
14
14
  ({
15
- lang,
15
+ lang = "text",
16
16
  code,
17
17
  copyable = false,
18
18
  copyText,
19
19
  copiedText,
20
- copyButtonAlign = "top",
20
+ copyButtonAlign = "top right",
21
+ onCopy,
21
22
  noBorder,
22
23
  wrapText = false,
23
24
  colorScheme,
@@ -31,71 +32,125 @@ const CodeBlockVanilla = React.forwardRef(
31
32
  const effectiveScheme = colorScheme ?? resolvedTheme;
32
33
  const prismTheme = effectiveScheme === "dark" ? prismReactRenderer.themes.nightOwl : prismReactRenderer.themes.nightOwlLight;
33
34
  const { style: cssStyles, vars } = cssProps.processCSSProp(css, colors);
34
- const mergedStyles = { ...cssStyles, ...style, ...dynamic.assignInlineVars(vars) };
35
+ const containerStyles = {
36
+ position: "relative",
37
+ ...cssStyles,
38
+ ...dynamic.assignInlineVars(vars)
39
+ };
35
40
  const [copied, setCopied] = React.useState(false);
41
+ const preRef = React.useRef(
42
+ null
43
+ );
44
+ const buttonWrapperRef = React.useRef(null);
45
+ const setPreRef = React.useCallback(
46
+ (node) => {
47
+ preRef.current = node;
48
+ if (typeof ref === "function") ref(node);
49
+ else if (ref) ref.current = node;
50
+ },
51
+ [ref]
52
+ );
53
+ React.useLayoutEffect(() => {
54
+ if (!copyable) return;
55
+ const pre2 = preRef.current;
56
+ const wrapper = buttonWrapperRef.current;
57
+ if (!pre2 || !wrapper) return;
58
+ const isLeftAlign = copyButtonAlign.includes("left");
59
+ const isBottomAlign = copyButtonAlign.includes("bottom");
60
+ const borderH = noBorder ? 0 : 2;
61
+ const update = () => {
62
+ if (!isLeftAlign) {
63
+ const vScrollbar = Math.max(0, pre2.offsetWidth - pre2.clientWidth - borderH);
64
+ wrapper.style.right = `${16 + vScrollbar}px`;
65
+ }
66
+ if (isBottomAlign) {
67
+ const hScrollbar = Math.max(0, pre2.offsetHeight - pre2.clientHeight - borderH);
68
+ wrapper.style.bottom = `${8 + hScrollbar}px`;
69
+ }
70
+ };
71
+ update();
72
+ const observer = new ResizeObserver(update);
73
+ observer.observe(pre2);
74
+ return () => observer.disconnect();
75
+ }, [copyable, copyButtonAlign, noBorder]);
36
76
  const handleCopy = async () => {
37
77
  try {
38
78
  await navigator.clipboard.writeText(code);
39
79
  setCopied(true);
80
+ onCopy?.();
40
81
  setTimeout(() => setCopied(false), 1500);
41
82
  } catch {
42
83
  }
43
84
  };
44
- return /* @__PURE__ */ jsxRuntime.jsx(prismReactRenderer.Highlight, { theme: prismTheme, code, language: lang, children: ({
45
- className: highlightClass,
46
- style: highlightStyle,
47
- tokens,
48
- getLineProps,
49
- getTokenProps
50
- }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: CodeBlock_vanilla_css.wrapper, children: [
51
- copyable && /* @__PURE__ */ jsxRuntime.jsx(
52
- "div",
53
- {
54
- className: [
55
- CodeBlock_vanilla_css.copyButtonWrapper,
56
- copyButtonAlign === "bottom" ? CodeBlock_vanilla_css.copyButtonWrapperBottom : CodeBlock_vanilla_css.copyButtonWrapperTop
57
- ].join(" "),
58
- children: /* @__PURE__ */ jsxRuntime.jsxs(
59
- Button_vanilla.ButtonVanilla,
85
+ const isBottom = copyButtonAlign.includes("bottom");
86
+ const isLeft = copyButtonAlign.includes("left");
87
+ const buttonPositionClass = isBottom ? isLeft ? CodeBlock_vanilla_css.copyButtonWrapperBottomLeft : CodeBlock_vanilla_css.copyButtonWrapperBottomRight : isLeft ? CodeBlock_vanilla_css.copyButtonWrapperTopLeft : CodeBlock_vanilla_css.copyButtonWrapperTop;
88
+ const copyButton = copyable ? /* @__PURE__ */ jsxRuntime.jsxs(
89
+ Button_vanilla.ButtonVanilla,
90
+ {
91
+ variant: "secondary",
92
+ ghost: true,
93
+ size: "small",
94
+ type: "button",
95
+ onClick: handleCopy,
96
+ css: {
97
+ color: "$hiContrast",
98
+ gap: "$1",
99
+ backgroundColor: "$codeBlockCopyButtonBg",
100
+ height: "32px"
101
+ },
102
+ children: [
103
+ /* @__PURE__ */ jsxRuntime.jsx(AccessibleIcon.AccessibleIcon, { label: copied ? "Copied" : "Copy", children: copied ? /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CheckIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CopyIcon, {}) }),
104
+ copied ? copiedText : copyText
105
+ ]
106
+ }
107
+ ) : null;
108
+ return /* @__PURE__ */ jsxRuntime.jsx(
109
+ prismReactRenderer.Highlight,
110
+ {
111
+ theme: prismTheme,
112
+ code,
113
+ language: prismReactRenderer.Prism.languages[lang] != null ? lang : "text",
114
+ children: ({
115
+ className: highlightClass,
116
+ style: highlightStyle,
117
+ tokens,
118
+ getLineProps,
119
+ getTokenProps
120
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyles, children: [
121
+ /* @__PURE__ */ jsxRuntime.jsx(
122
+ "pre",
60
123
  {
61
- variant: "secondary",
62
- ghost: true,
63
- size: "small",
64
- type: "button",
65
- onClick: handleCopy,
66
- css: { color: "$hiContrast", gap: "$1" },
67
- children: [
68
- /* @__PURE__ */ jsxRuntime.jsx(AccessibleIcon.AccessibleIcon, { label: copied ? "Copied" : "Copy", children: copied ? /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CheckIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CopyIcon, {}) }),
69
- copied ? copiedText : copyText
70
- ]
124
+ ref: setPreRef,
125
+ className: [CodeBlock_vanilla_css.pre, noBorder ? CodeBlock_vanilla_css.preNoBorder : "", highlightClass, className].filter(Boolean).join(" "),
126
+ style: {
127
+ maxHeight,
128
+ ...highlightStyle,
129
+ backgroundColor: "inherit",
130
+ ...style
131
+ },
132
+ ...props,
133
+ children: /* @__PURE__ */ jsxRuntime.jsx(
134
+ "div",
135
+ {
136
+ className: [CodeBlock_vanilla_css.codeContent, copyable && isBottom ? CodeBlock_vanilla_css.codeContentBottomPadding : ""].filter(Boolean).join(" "),
137
+ children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
138
+ "div",
139
+ {
140
+ ...getLineProps({ line }),
141
+ style: wrapText ? { whiteSpace: "pre-wrap", wordBreak: "break-all" } : void 0,
142
+ children: line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
143
+ },
144
+ i
145
+ ))
146
+ }
147
+ )
71
148
  }
72
- )
73
- }
74
- ),
75
- /* @__PURE__ */ jsxRuntime.jsx(
76
- "pre",
77
- {
78
- ref,
79
- className: [CodeBlock_vanilla_css.pre, noBorder ? CodeBlock_vanilla_css.preNoBorder : "", highlightClass, className].filter(Boolean).join(" "),
80
- style: {
81
- maxHeight,
82
- ...highlightStyle,
83
- backgroundColor: "transparent",
84
- ...mergedStyles
85
- },
86
- ...props,
87
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: CodeBlock_vanilla_css.codeContent, children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
88
- "div",
89
- {
90
- ...getLineProps({ line }),
91
- style: wrapText ? { whiteSpace: "normal" } : void 0,
92
- children: line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
93
- },
94
- i
95
- )) })
96
- }
97
- )
98
- ] }) });
149
+ ),
150
+ copyButton && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: buttonWrapperRef, className: buttonPositionClass, children: copyButton })
151
+ ] })
152
+ }
153
+ );
99
154
  }
100
155
  );
101
156
  CodeBlockVanilla.displayName = "CodeBlockVanilla";
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlock.vanilla.cjs","sources":["../../../components/CodeBlock/CodeBlock.vanilla.tsx"],"sourcesContent":["import { CheckIcon, CopyIcon } from '@radix-ui/react-icons';\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport { Highlight, Language, themes } from 'prism-react-renderer';\nimport React, { forwardRef, HTMLAttributes, useState } from 'react';\n\nimport { CSSProps, processCSSProp } from '../../styles/cssProps';\nimport { useVanillaExtractTheme } from '../../styles/themeContext';\nimport { AccessibleIcon } from '../AccessibleIcon';\nimport { ButtonVanilla } from '../Button';\nimport {\n codeContent,\n copyButtonWrapper,\n copyButtonWrapperBottom,\n copyButtonWrapperTop,\n pre,\n preNoBorder,\n wrapper,\n} from './CodeBlock.vanilla.css';\n\nexport interface CodeBlockVanillaProps\n extends Omit<HTMLAttributes<HTMLPreElement>, 'css'>,\n CSSProps {\n lang: Language;\n code: string;\n copyable?: boolean;\n copyText?: string;\n copiedText?: string;\n copyButtonAlign?: 'top' | 'bottom';\n noBorder?: boolean;\n wrapText?: boolean;\n colorScheme?: 'light' | 'dark';\n maxHeight?: number | string;\n}\n\nexport const CodeBlockVanilla = forwardRef<HTMLPreElement, CodeBlockVanillaProps>(\n (\n {\n lang,\n code,\n copyable = false,\n copyText,\n copiedText,\n copyButtonAlign = 'top',\n noBorder,\n wrapText = false,\n colorScheme,\n maxHeight = 424,\n css,\n style,\n className,\n ...props\n },\n ref,\n ) => {\n const { colors, resolvedTheme } = useVanillaExtractTheme();\n const effectiveScheme = colorScheme ?? resolvedTheme;\n const prismTheme = effectiveScheme === 'dark' ? themes.nightOwl : themes.nightOwlLight;\n\n const { style: cssStyles, vars } = processCSSProp(css, colors);\n const mergedStyles = { ...cssStyles, ...style, ...assignInlineVars(vars) };\n\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n } catch {\n // clipboard write failed (e.g. permission denied) — leave UI unchanged\n }\n };\n\n return (\n <Highlight theme={prismTheme} code={code} language={lang}>\n {({\n className: highlightClass,\n style: highlightStyle,\n tokens,\n getLineProps,\n getTokenProps,\n }) => (\n <div className={wrapper}>\n {copyable && (\n <div\n className={[\n copyButtonWrapper,\n copyButtonAlign === 'bottom' ? copyButtonWrapperBottom : copyButtonWrapperTop,\n ].join(' ')}\n >\n <ButtonVanilla\n variant=\"secondary\"\n ghost\n size=\"small\"\n type=\"button\"\n onClick={handleCopy}\n css={{ color: '$hiContrast', gap: '$1' }}\n >\n <AccessibleIcon label={copied ? 'Copied' : 'Copy'}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n </AccessibleIcon>\n {copied ? copiedText : copyText}\n </ButtonVanilla>\n </div>\n )}\n <pre\n ref={ref}\n className={[pre, noBorder ? preNoBorder : '', highlightClass, className]\n .filter(Boolean)\n .join(' ')}\n style={{\n maxHeight,\n ...highlightStyle,\n backgroundColor: 'transparent',\n ...mergedStyles,\n }}\n {...props}\n >\n <div className={codeContent}>\n {tokens.map((line, i) => (\n <div\n key={i}\n {...getLineProps({ line })}\n style={wrapText ? { whiteSpace: 'normal' } : undefined}\n >\n {line.map((token, key) => (\n <span key={key} {...getTokenProps({ token })} />\n ))}\n </div>\n ))}\n </div>\n </pre>\n </div>\n )}\n </Highlight>\n );\n },\n);\n\nCodeBlockVanilla.displayName = 'CodeBlockVanilla';\n"],"names":["forwardRef","useVanillaExtractTheme","themes","processCSSProp","assignInlineVars","useState","Highlight","jsxs","wrapper","jsx","copyButtonWrapper","copyButtonWrapperBottom","copyButtonWrapperTop","ButtonVanilla","AccessibleIcon","CheckIcon","CopyIcon","pre","preNoBorder","codeContent"],"mappings":"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"}
1
+ {"version":3,"file":"CodeBlock.vanilla.cjs","sources":["../../../components/CodeBlock/CodeBlock.vanilla.tsx"],"sourcesContent":["import './prism-extend';\n\nimport { CheckIcon, CopyIcon } from '@radix-ui/react-icons';\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport { Highlight, Language, Prism, themes } from 'prism-react-renderer';\nimport React, {\n forwardRef,\n HTMLAttributes,\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { CSSProps, processCSSProp } from '../../styles/cssProps';\nimport { useVanillaExtractTheme } from '../../styles/themeContext';\nimport { AccessibleIcon } from '../AccessibleIcon';\nimport { ButtonVanilla } from '../Button';\nimport {\n codeContent,\n codeContentBottomPadding,\n copyButtonWrapperBottomLeft,\n copyButtonWrapperBottomRight,\n copyButtonWrapperTop,\n copyButtonWrapperTopLeft,\n pre,\n preNoBorder,\n} from './CodeBlock.vanilla.css';\nimport type { CodeBlockCopyButtonAlign, CodeBlockLanguage } from './index';\n\nexport interface CodeBlockVanillaProps\n extends Omit<HTMLAttributes<HTMLPreElement>, 'css'>,\n CSSProps {\n lang?: CodeBlockLanguage;\n code: string;\n copyable?: boolean;\n copyText?: string;\n copiedText?: string;\n copyButtonAlign?: CodeBlockCopyButtonAlign;\n onCopy?: () => void;\n noBorder?: boolean;\n wrapText?: boolean;\n colorScheme?: 'light' | 'dark';\n maxHeight?: number | string;\n}\n\nexport const CodeBlockVanilla = forwardRef<HTMLPreElement, CodeBlockVanillaProps>(\n (\n {\n lang = 'text',\n code,\n copyable = false,\n copyText,\n copiedText,\n copyButtonAlign = 'top right',\n onCopy,\n noBorder,\n wrapText = false,\n colorScheme,\n maxHeight = 424,\n css,\n style,\n className,\n ...props\n },\n ref,\n ) => {\n const { colors, resolvedTheme } = useVanillaExtractTheme();\n const effectiveScheme = colorScheme ?? resolvedTheme;\n const prismTheme = effectiveScheme === 'dark' ? themes.nightOwl : themes.nightOwlLight;\n\n const { style: cssStyles, vars } = processCSSProp(css, colors);\n const containerStyles = {\n position: 'relative' as const,\n ...cssStyles,\n ...assignInlineVars(vars),\n };\n\n const [copied, setCopied] = useState(false);\n\n const preRef = useRef<HTMLPreElement | null>(\n null,\n ) as React.MutableRefObject<HTMLPreElement | null>;\n const buttonWrapperRef = useRef<HTMLDivElement>(null);\n\n const setPreRef = useCallback(\n (node: HTMLPreElement | null) => {\n preRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLPreElement | null>).current = node;\n },\n [ref],\n );\n\n useLayoutEffect(() => {\n if (!copyable) return;\n const pre = preRef.current;\n const wrapper = buttonWrapperRef.current;\n if (!pre || !wrapper) return;\n\n const isLeftAlign = copyButtonAlign.includes('left');\n const isBottomAlign = copyButtonAlign.includes('bottom');\n const borderH = noBorder ? 0 : 2;\n\n const update = () => {\n if (!isLeftAlign) {\n const vScrollbar = Math.max(0, pre.offsetWidth - pre.clientWidth - borderH);\n wrapper.style.right = `${16 + vScrollbar}px`;\n }\n if (isBottomAlign) {\n const hScrollbar = Math.max(0, pre.offsetHeight - pre.clientHeight - borderH);\n wrapper.style.bottom = `${8 + hScrollbar}px`;\n }\n };\n\n update();\n const observer = new ResizeObserver(update);\n observer.observe(pre);\n return () => observer.disconnect();\n }, [copyable, copyButtonAlign, noBorder]);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n onCopy?.();\n setTimeout(() => setCopied(false), 1500);\n } catch {\n // clipboard write failed (e.g. permission denied) — leave UI unchanged\n }\n };\n\n const isBottom = copyButtonAlign.includes('bottom');\n const isLeft = copyButtonAlign.includes('left');\n const buttonPositionClass = isBottom\n ? isLeft\n ? copyButtonWrapperBottomLeft\n : copyButtonWrapperBottomRight\n : isLeft\n ? copyButtonWrapperTopLeft\n : copyButtonWrapperTop;\n\n const copyButton = copyable ? (\n <ButtonVanilla\n variant=\"secondary\"\n ghost\n size=\"small\"\n type=\"button\"\n onClick={handleCopy}\n css={{\n color: '$hiContrast',\n gap: '$1',\n backgroundColor: '$codeBlockCopyButtonBg',\n height: '32px',\n }}\n >\n <AccessibleIcon label={copied ? 'Copied' : 'Copy'}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n </AccessibleIcon>\n {copied ? copiedText : copyText}\n </ButtonVanilla>\n ) : null;\n\n return (\n <Highlight\n theme={prismTheme}\n code={code}\n language={(Prism.languages[lang] != null ? lang : 'text') as Language}\n >\n {({\n className: highlightClass,\n style: highlightStyle,\n tokens,\n getLineProps,\n getTokenProps,\n }) => (\n <div style={containerStyles}>\n <pre\n ref={setPreRef}\n className={[pre, noBorder ? preNoBorder : '', highlightClass, className]\n .filter(Boolean)\n .join(' ')}\n style={{\n maxHeight,\n ...highlightStyle,\n backgroundColor: 'inherit',\n ...style,\n }}\n {...props}\n >\n <div\n className={[codeContent, copyable && isBottom ? codeContentBottomPadding : '']\n .filter(Boolean)\n .join(' ')}\n >\n {tokens.map((line, i) => (\n <div\n key={i}\n {...getLineProps({ line })}\n style={\n wrapText ? { whiteSpace: 'pre-wrap', wordBreak: 'break-all' } : undefined\n }\n >\n {line.map((token, key) => (\n <span key={key} {...getTokenProps({ token })} />\n ))}\n </div>\n ))}\n </div>\n </pre>\n {copyButton && (\n <div ref={buttonWrapperRef} className={buttonPositionClass}>\n {copyButton}\n </div>\n )}\n </div>\n )}\n </Highlight>\n );\n },\n);\n\nCodeBlockVanilla.displayName = 'CodeBlockVanilla';\n"],"names":["forwardRef","useVanillaExtractTheme","themes","processCSSProp","assignInlineVars","useState","useRef","useCallback","useLayoutEffect","pre","copyButtonWrapperBottomLeft","copyButtonWrapperBottomRight","copyButtonWrapperTopLeft","copyButtonWrapperTop","jsxs","ButtonVanilla","jsx","AccessibleIcon","CheckIcon","CopyIcon","Highlight","Prism","preNoBorder","codeContent","codeContentBottomPadding"],"mappings":"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"}
@@ -1,18 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  ;/* empty css */
4
- var wrapper = "_1krwcuz0";
5
- var pre = "_1krwcuz1";
6
- var preNoBorder = "_1krwcuz2";
7
- var codeContent = "_1krwcuz3";
8
- var copyButtonWrapper = "_1krwcuz4";
9
- var copyButtonWrapperTop = "_1krwcuz5";
10
- var copyButtonWrapperBottom = "_1krwcuz6";
4
+ var pre = "_1krwcuz0";
5
+ var preNoBorder = "_1krwcuz1";
6
+ var codeContent = "_1krwcuz2";
7
+ var codeContentBottomPadding = "_1krwcuz3";
8
+ var copyButtonWrapperTop = "_1krwcuz4";
9
+ var copyButtonWrapperTopLeft = "_1krwcuz5";
10
+ var copyButtonWrapperBottomRight = "_1krwcuz6";
11
+ var copyButtonWrapperBottomLeft = "_1krwcuz7";
11
12
  exports.codeContent = codeContent;
12
- exports.copyButtonWrapper = copyButtonWrapper;
13
- exports.copyButtonWrapperBottom = copyButtonWrapperBottom;
13
+ exports.codeContentBottomPadding = codeContentBottomPadding;
14
+ exports.copyButtonWrapperBottomLeft = copyButtonWrapperBottomLeft;
15
+ exports.copyButtonWrapperBottomRight = copyButtonWrapperBottomRight;
14
16
  exports.copyButtonWrapperTop = copyButtonWrapperTop;
17
+ exports.copyButtonWrapperTopLeft = copyButtonWrapperTopLeft;
15
18
  exports.pre = pre;
16
19
  exports.preNoBorder = preNoBorder;
17
- exports.wrapper = wrapper;
18
20
  //# sourceMappingURL=CodeBlock.vanilla.css.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlock.vanilla.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CodeBlock.vanilla.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
@@ -1,18 +1,20 @@
1
1
  /* empty css */
2
- var wrapper = "_1krwcuz0";
3
- var pre = "_1krwcuz1";
4
- var preNoBorder = "_1krwcuz2";
5
- var codeContent = "_1krwcuz3";
6
- var copyButtonWrapper = "_1krwcuz4";
7
- var copyButtonWrapperTop = "_1krwcuz5";
8
- var copyButtonWrapperBottom = "_1krwcuz6";
2
+ var pre = "_1krwcuz0";
3
+ var preNoBorder = "_1krwcuz1";
4
+ var codeContent = "_1krwcuz2";
5
+ var codeContentBottomPadding = "_1krwcuz3";
6
+ var copyButtonWrapperTop = "_1krwcuz4";
7
+ var copyButtonWrapperTopLeft = "_1krwcuz5";
8
+ var copyButtonWrapperBottomRight = "_1krwcuz6";
9
+ var copyButtonWrapperBottomLeft = "_1krwcuz7";
9
10
  export {
10
11
  codeContent,
11
- copyButtonWrapper,
12
- copyButtonWrapperBottom,
12
+ codeContentBottomPadding,
13
+ copyButtonWrapperBottomLeft,
14
+ copyButtonWrapperBottomRight,
13
15
  copyButtonWrapperTop,
16
+ copyButtonWrapperTopLeft,
14
17
  pre,
15
- preNoBorder,
16
- wrapper
18
+ preNoBorder
17
19
  };
18
20
  //# sourceMappingURL=CodeBlock.vanilla.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlock.vanilla.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"CodeBlock.vanilla.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -1,21 +1,22 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { CheckIcon, CopyIcon } from "@radix-ui/react-icons";
3
3
  import { assignInlineVars } from "@vanilla-extract/dynamic";
4
- import { themes, Highlight } from "prism-react-renderer";
5
- import { forwardRef, useState } from "react";
4
+ import { themes, Highlight, Prism } from "prism-react-renderer";
5
+ import { forwardRef, useState, useRef, useCallback, useLayoutEffect } from "react";
6
6
  import { processCSSProp } from "../../styles/cssProps.js";
7
7
  import { useVanillaExtractTheme } from "../../styles/themeContext.js";
8
- import { wrapper, copyButtonWrapper, copyButtonWrapperBottom, copyButtonWrapperTop, pre, preNoBorder, codeContent } from "./CodeBlock.vanilla.css.js";
8
+ import { pre, preNoBorder, codeContent, codeContentBottomPadding, copyButtonWrapperBottomLeft, copyButtonWrapperBottomRight, copyButtonWrapperTopLeft, copyButtonWrapperTop } from "./CodeBlock.vanilla.css.js";
9
9
  import { ButtonVanilla } from "../Button/Button.vanilla.js";
10
10
  import { AccessibleIcon } from "../AccessibleIcon/AccessibleIcon.js";
11
11
  const CodeBlockVanilla = forwardRef(
12
12
  ({
13
- lang,
13
+ lang = "text",
14
14
  code,
15
15
  copyable = false,
16
16
  copyText,
17
17
  copiedText,
18
- copyButtonAlign = "top",
18
+ copyButtonAlign = "top right",
19
+ onCopy,
19
20
  noBorder,
20
21
  wrapText = false,
21
22
  colorScheme,
@@ -29,71 +30,125 @@ const CodeBlockVanilla = forwardRef(
29
30
  const effectiveScheme = colorScheme ?? resolvedTheme;
30
31
  const prismTheme = effectiveScheme === "dark" ? themes.nightOwl : themes.nightOwlLight;
31
32
  const { style: cssStyles, vars } = processCSSProp(css, colors);
32
- const mergedStyles = { ...cssStyles, ...style, ...assignInlineVars(vars) };
33
+ const containerStyles = {
34
+ position: "relative",
35
+ ...cssStyles,
36
+ ...assignInlineVars(vars)
37
+ };
33
38
  const [copied, setCopied] = useState(false);
39
+ const preRef = useRef(
40
+ null
41
+ );
42
+ const buttonWrapperRef = useRef(null);
43
+ const setPreRef = useCallback(
44
+ (node) => {
45
+ preRef.current = node;
46
+ if (typeof ref === "function") ref(node);
47
+ else if (ref) ref.current = node;
48
+ },
49
+ [ref]
50
+ );
51
+ useLayoutEffect(() => {
52
+ if (!copyable) return;
53
+ const pre2 = preRef.current;
54
+ const wrapper = buttonWrapperRef.current;
55
+ if (!pre2 || !wrapper) return;
56
+ const isLeftAlign = copyButtonAlign.includes("left");
57
+ const isBottomAlign = copyButtonAlign.includes("bottom");
58
+ const borderH = noBorder ? 0 : 2;
59
+ const update = () => {
60
+ if (!isLeftAlign) {
61
+ const vScrollbar = Math.max(0, pre2.offsetWidth - pre2.clientWidth - borderH);
62
+ wrapper.style.right = `${16 + vScrollbar}px`;
63
+ }
64
+ if (isBottomAlign) {
65
+ const hScrollbar = Math.max(0, pre2.offsetHeight - pre2.clientHeight - borderH);
66
+ wrapper.style.bottom = `${8 + hScrollbar}px`;
67
+ }
68
+ };
69
+ update();
70
+ const observer = new ResizeObserver(update);
71
+ observer.observe(pre2);
72
+ return () => observer.disconnect();
73
+ }, [copyable, copyButtonAlign, noBorder]);
34
74
  const handleCopy = async () => {
35
75
  try {
36
76
  await navigator.clipboard.writeText(code);
37
77
  setCopied(true);
78
+ onCopy?.();
38
79
  setTimeout(() => setCopied(false), 1500);
39
80
  } catch {
40
81
  }
41
82
  };
42
- return /* @__PURE__ */ jsx(Highlight, { theme: prismTheme, code, language: lang, children: ({
43
- className: highlightClass,
44
- style: highlightStyle,
45
- tokens,
46
- getLineProps,
47
- getTokenProps
48
- }) => /* @__PURE__ */ jsxs("div", { className: wrapper, children: [
49
- copyable && /* @__PURE__ */ jsx(
50
- "div",
51
- {
52
- className: [
53
- copyButtonWrapper,
54
- copyButtonAlign === "bottom" ? copyButtonWrapperBottom : copyButtonWrapperTop
55
- ].join(" "),
56
- children: /* @__PURE__ */ jsxs(
57
- ButtonVanilla,
83
+ const isBottom = copyButtonAlign.includes("bottom");
84
+ const isLeft = copyButtonAlign.includes("left");
85
+ const buttonPositionClass = isBottom ? isLeft ? copyButtonWrapperBottomLeft : copyButtonWrapperBottomRight : isLeft ? copyButtonWrapperTopLeft : copyButtonWrapperTop;
86
+ const copyButton = copyable ? /* @__PURE__ */ jsxs(
87
+ ButtonVanilla,
88
+ {
89
+ variant: "secondary",
90
+ ghost: true,
91
+ size: "small",
92
+ type: "button",
93
+ onClick: handleCopy,
94
+ css: {
95
+ color: "$hiContrast",
96
+ gap: "$1",
97
+ backgroundColor: "$codeBlockCopyButtonBg",
98
+ height: "32px"
99
+ },
100
+ children: [
101
+ /* @__PURE__ */ jsx(AccessibleIcon, { label: copied ? "Copied" : "Copy", children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}) }),
102
+ copied ? copiedText : copyText
103
+ ]
104
+ }
105
+ ) : null;
106
+ return /* @__PURE__ */ jsx(
107
+ Highlight,
108
+ {
109
+ theme: prismTheme,
110
+ code,
111
+ language: Prism.languages[lang] != null ? lang : "text",
112
+ children: ({
113
+ className: highlightClass,
114
+ style: highlightStyle,
115
+ tokens,
116
+ getLineProps,
117
+ getTokenProps
118
+ }) => /* @__PURE__ */ jsxs("div", { style: containerStyles, children: [
119
+ /* @__PURE__ */ jsx(
120
+ "pre",
58
121
  {
59
- variant: "secondary",
60
- ghost: true,
61
- size: "small",
62
- type: "button",
63
- onClick: handleCopy,
64
- css: { color: "$hiContrast", gap: "$1" },
65
- children: [
66
- /* @__PURE__ */ jsx(AccessibleIcon, { label: copied ? "Copied" : "Copy", children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}) }),
67
- copied ? copiedText : copyText
68
- ]
122
+ ref: setPreRef,
123
+ className: [pre, noBorder ? preNoBorder : "", highlightClass, className].filter(Boolean).join(" "),
124
+ style: {
125
+ maxHeight,
126
+ ...highlightStyle,
127
+ backgroundColor: "inherit",
128
+ ...style
129
+ },
130
+ ...props,
131
+ children: /* @__PURE__ */ jsx(
132
+ "div",
133
+ {
134
+ className: [codeContent, copyable && isBottom ? codeContentBottomPadding : ""].filter(Boolean).join(" "),
135
+ children: tokens.map((line, i) => /* @__PURE__ */ jsx(
136
+ "div",
137
+ {
138
+ ...getLineProps({ line }),
139
+ style: wrapText ? { whiteSpace: "pre-wrap", wordBreak: "break-all" } : void 0,
140
+ children: line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
141
+ },
142
+ i
143
+ ))
144
+ }
145
+ )
69
146
  }
70
- )
71
- }
72
- ),
73
- /* @__PURE__ */ jsx(
74
- "pre",
75
- {
76
- ref,
77
- className: [pre, noBorder ? preNoBorder : "", highlightClass, className].filter(Boolean).join(" "),
78
- style: {
79
- maxHeight,
80
- ...highlightStyle,
81
- backgroundColor: "transparent",
82
- ...mergedStyles
83
- },
84
- ...props,
85
- children: /* @__PURE__ */ jsx("div", { className: codeContent, children: tokens.map((line, i) => /* @__PURE__ */ jsx(
86
- "div",
87
- {
88
- ...getLineProps({ line }),
89
- style: wrapText ? { whiteSpace: "normal" } : void 0,
90
- children: line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
91
- },
92
- i
93
- )) })
94
- }
95
- )
96
- ] }) });
147
+ ),
148
+ copyButton && /* @__PURE__ */ jsx("div", { ref: buttonWrapperRef, className: buttonPositionClass, children: copyButton })
149
+ ] })
150
+ }
151
+ );
97
152
  }
98
153
  );
99
154
  CodeBlockVanilla.displayName = "CodeBlockVanilla";
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlock.vanilla.js","sources":["../../../components/CodeBlock/CodeBlock.vanilla.tsx"],"sourcesContent":["import { CheckIcon, CopyIcon } from '@radix-ui/react-icons';\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport { Highlight, Language, themes } from 'prism-react-renderer';\nimport React, { forwardRef, HTMLAttributes, useState } from 'react';\n\nimport { CSSProps, processCSSProp } from '../../styles/cssProps';\nimport { useVanillaExtractTheme } from '../../styles/themeContext';\nimport { AccessibleIcon } from '../AccessibleIcon';\nimport { ButtonVanilla } from '../Button';\nimport {\n codeContent,\n copyButtonWrapper,\n copyButtonWrapperBottom,\n copyButtonWrapperTop,\n pre,\n preNoBorder,\n wrapper,\n} from './CodeBlock.vanilla.css';\n\nexport interface CodeBlockVanillaProps\n extends Omit<HTMLAttributes<HTMLPreElement>, 'css'>,\n CSSProps {\n lang: Language;\n code: string;\n copyable?: boolean;\n copyText?: string;\n copiedText?: string;\n copyButtonAlign?: 'top' | 'bottom';\n noBorder?: boolean;\n wrapText?: boolean;\n colorScheme?: 'light' | 'dark';\n maxHeight?: number | string;\n}\n\nexport const CodeBlockVanilla = forwardRef<HTMLPreElement, CodeBlockVanillaProps>(\n (\n {\n lang,\n code,\n copyable = false,\n copyText,\n copiedText,\n copyButtonAlign = 'top',\n noBorder,\n wrapText = false,\n colorScheme,\n maxHeight = 424,\n css,\n style,\n className,\n ...props\n },\n ref,\n ) => {\n const { colors, resolvedTheme } = useVanillaExtractTheme();\n const effectiveScheme = colorScheme ?? resolvedTheme;\n const prismTheme = effectiveScheme === 'dark' ? themes.nightOwl : themes.nightOwlLight;\n\n const { style: cssStyles, vars } = processCSSProp(css, colors);\n const mergedStyles = { ...cssStyles, ...style, ...assignInlineVars(vars) };\n\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n } catch {\n // clipboard write failed (e.g. permission denied) — leave UI unchanged\n }\n };\n\n return (\n <Highlight theme={prismTheme} code={code} language={lang}>\n {({\n className: highlightClass,\n style: highlightStyle,\n tokens,\n getLineProps,\n getTokenProps,\n }) => (\n <div className={wrapper}>\n {copyable && (\n <div\n className={[\n copyButtonWrapper,\n copyButtonAlign === 'bottom' ? copyButtonWrapperBottom : copyButtonWrapperTop,\n ].join(' ')}\n >\n <ButtonVanilla\n variant=\"secondary\"\n ghost\n size=\"small\"\n type=\"button\"\n onClick={handleCopy}\n css={{ color: '$hiContrast', gap: '$1' }}\n >\n <AccessibleIcon label={copied ? 'Copied' : 'Copy'}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n </AccessibleIcon>\n {copied ? copiedText : copyText}\n </ButtonVanilla>\n </div>\n )}\n <pre\n ref={ref}\n className={[pre, noBorder ? preNoBorder : '', highlightClass, className]\n .filter(Boolean)\n .join(' ')}\n style={{\n maxHeight,\n ...highlightStyle,\n backgroundColor: 'transparent',\n ...mergedStyles,\n }}\n {...props}\n >\n <div className={codeContent}>\n {tokens.map((line, i) => (\n <div\n key={i}\n {...getLineProps({ line })}\n style={wrapText ? { whiteSpace: 'normal' } : undefined}\n >\n {line.map((token, key) => (\n <span key={key} {...getTokenProps({ token })} />\n ))}\n </div>\n ))}\n </div>\n </pre>\n </div>\n )}\n </Highlight>\n );\n },\n);\n\nCodeBlockVanilla.displayName = 'CodeBlockVanilla';\n"],"names":[],"mappings":";;;;;;;;;;AAkCO,MAAM,mBAAmB;AAAA,EAC9B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,EAAE,QAAQ,cAAA,IAAkB,uBAAA;AAClC,UAAM,kBAAkB,eAAe;AACvC,UAAM,aAAa,oBAAoB,SAAS,OAAO,WAAW,OAAO;AAEzE,UAAM,EAAE,OAAO,WAAW,SAAS,eAAe,KAAK,MAAM;AAC7D,UAAM,eAAe,EAAE,GAAG,WAAW,GAAG,OAAO,GAAG,iBAAiB,IAAI,EAAA;AAEvE,UAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,UAAM,aAAa,YAAY;AAC7B,UAAI;AACF,cAAM,UAAU,UAAU,UAAU,IAAI;AACxC,kBAAU,IAAI;AACd,mBAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAAA,MACzC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,+BACG,WAAA,EAAU,OAAO,YAAY,MAAY,UAAU,MACjD,UAAA,CAAC;AAAA,MACA,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IAAA,MAEA,qBAAC,OAAA,EAAI,WAAW,SACb,UAAA;AAAA,MAAA,YACC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,oBAAoB,WAAW,0BAA0B;AAAA,UAAA,EACzD,KAAK,GAAG;AAAA,UAEV,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,OAAK;AAAA,cACL,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS;AAAA,cACT,KAAK,EAAE,OAAO,eAAe,KAAK,KAAA;AAAA,cAElC,UAAA;AAAA,gBAAA,oBAAC,gBAAA,EAAe,OAAO,SAAS,WAAW,QACxC,UAAA,SAAS,oBAAC,WAAA,EAAU,IAAK,oBAAC,UAAA,CAAA,CAAS,GACtC;AAAA,gBACC,SAAS,aAAa;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACzB;AAAA,MAAA;AAAA,MAGJ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC;AAAA,UACA,WAAW,CAAC,KAAK,WAAW,cAAc,IAAI,gBAAgB,SAAS,EACpE,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,UACX,OAAO;AAAA,YACL;AAAA,YACA,GAAG;AAAA,YACH,iBAAiB;AAAA,YACjB,GAAG;AAAA,UAAA;AAAA,UAEJ,GAAG;AAAA,UAEJ,UAAA,oBAAC,SAAI,WAAW,aACb,iBAAO,IAAI,CAAC,MAAM,MACjB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEE,GAAG,aAAa,EAAE,MAAM;AAAA,cACzB,OAAO,WAAW,EAAE,YAAY,aAAa;AAAA,cAE5C,UAAA,KAAK,IAAI,CAAC,OAAO,QAChB,oBAAC,QAAA,EAAgB,GAAG,cAAc,EAAE,MAAA,CAAO,EAAA,GAAhC,GAAmC,CAC/C;AAAA,YAAA;AAAA,YANI;AAAA,UAAA,CAQR,EAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,EAAA,CACF,EAAA,CAEJ;AAAA,EAEJ;AACF;AAEA,iBAAiB,cAAc;"}
1
+ {"version":3,"file":"CodeBlock.vanilla.js","sources":["../../../components/CodeBlock/CodeBlock.vanilla.tsx"],"sourcesContent":["import './prism-extend';\n\nimport { CheckIcon, CopyIcon } from '@radix-ui/react-icons';\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport { Highlight, Language, Prism, themes } from 'prism-react-renderer';\nimport React, {\n forwardRef,\n HTMLAttributes,\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { CSSProps, processCSSProp } from '../../styles/cssProps';\nimport { useVanillaExtractTheme } from '../../styles/themeContext';\nimport { AccessibleIcon } from '../AccessibleIcon';\nimport { ButtonVanilla } from '../Button';\nimport {\n codeContent,\n codeContentBottomPadding,\n copyButtonWrapperBottomLeft,\n copyButtonWrapperBottomRight,\n copyButtonWrapperTop,\n copyButtonWrapperTopLeft,\n pre,\n preNoBorder,\n} from './CodeBlock.vanilla.css';\nimport type { CodeBlockCopyButtonAlign, CodeBlockLanguage } from './index';\n\nexport interface CodeBlockVanillaProps\n extends Omit<HTMLAttributes<HTMLPreElement>, 'css'>,\n CSSProps {\n lang?: CodeBlockLanguage;\n code: string;\n copyable?: boolean;\n copyText?: string;\n copiedText?: string;\n copyButtonAlign?: CodeBlockCopyButtonAlign;\n onCopy?: () => void;\n noBorder?: boolean;\n wrapText?: boolean;\n colorScheme?: 'light' | 'dark';\n maxHeight?: number | string;\n}\n\nexport const CodeBlockVanilla = forwardRef<HTMLPreElement, CodeBlockVanillaProps>(\n (\n {\n lang = 'text',\n code,\n copyable = false,\n copyText,\n copiedText,\n copyButtonAlign = 'top right',\n onCopy,\n noBorder,\n wrapText = false,\n colorScheme,\n maxHeight = 424,\n css,\n style,\n className,\n ...props\n },\n ref,\n ) => {\n const { colors, resolvedTheme } = useVanillaExtractTheme();\n const effectiveScheme = colorScheme ?? resolvedTheme;\n const prismTheme = effectiveScheme === 'dark' ? themes.nightOwl : themes.nightOwlLight;\n\n const { style: cssStyles, vars } = processCSSProp(css, colors);\n const containerStyles = {\n position: 'relative' as const,\n ...cssStyles,\n ...assignInlineVars(vars),\n };\n\n const [copied, setCopied] = useState(false);\n\n const preRef = useRef<HTMLPreElement | null>(\n null,\n ) as React.MutableRefObject<HTMLPreElement | null>;\n const buttonWrapperRef = useRef<HTMLDivElement>(null);\n\n const setPreRef = useCallback(\n (node: HTMLPreElement | null) => {\n preRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLPreElement | null>).current = node;\n },\n [ref],\n );\n\n useLayoutEffect(() => {\n if (!copyable) return;\n const pre = preRef.current;\n const wrapper = buttonWrapperRef.current;\n if (!pre || !wrapper) return;\n\n const isLeftAlign = copyButtonAlign.includes('left');\n const isBottomAlign = copyButtonAlign.includes('bottom');\n const borderH = noBorder ? 0 : 2;\n\n const update = () => {\n if (!isLeftAlign) {\n const vScrollbar = Math.max(0, pre.offsetWidth - pre.clientWidth - borderH);\n wrapper.style.right = `${16 + vScrollbar}px`;\n }\n if (isBottomAlign) {\n const hScrollbar = Math.max(0, pre.offsetHeight - pre.clientHeight - borderH);\n wrapper.style.bottom = `${8 + hScrollbar}px`;\n }\n };\n\n update();\n const observer = new ResizeObserver(update);\n observer.observe(pre);\n return () => observer.disconnect();\n }, [copyable, copyButtonAlign, noBorder]);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n onCopy?.();\n setTimeout(() => setCopied(false), 1500);\n } catch {\n // clipboard write failed (e.g. permission denied) — leave UI unchanged\n }\n };\n\n const isBottom = copyButtonAlign.includes('bottom');\n const isLeft = copyButtonAlign.includes('left');\n const buttonPositionClass = isBottom\n ? isLeft\n ? copyButtonWrapperBottomLeft\n : copyButtonWrapperBottomRight\n : isLeft\n ? copyButtonWrapperTopLeft\n : copyButtonWrapperTop;\n\n const copyButton = copyable ? (\n <ButtonVanilla\n variant=\"secondary\"\n ghost\n size=\"small\"\n type=\"button\"\n onClick={handleCopy}\n css={{\n color: '$hiContrast',\n gap: '$1',\n backgroundColor: '$codeBlockCopyButtonBg',\n height: '32px',\n }}\n >\n <AccessibleIcon label={copied ? 'Copied' : 'Copy'}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n </AccessibleIcon>\n {copied ? copiedText : copyText}\n </ButtonVanilla>\n ) : null;\n\n return (\n <Highlight\n theme={prismTheme}\n code={code}\n language={(Prism.languages[lang] != null ? lang : 'text') as Language}\n >\n {({\n className: highlightClass,\n style: highlightStyle,\n tokens,\n getLineProps,\n getTokenProps,\n }) => (\n <div style={containerStyles}>\n <pre\n ref={setPreRef}\n className={[pre, noBorder ? preNoBorder : '', highlightClass, className]\n .filter(Boolean)\n .join(' ')}\n style={{\n maxHeight,\n ...highlightStyle,\n backgroundColor: 'inherit',\n ...style,\n }}\n {...props}\n >\n <div\n className={[codeContent, copyable && isBottom ? codeContentBottomPadding : '']\n .filter(Boolean)\n .join(' ')}\n >\n {tokens.map((line, i) => (\n <div\n key={i}\n {...getLineProps({ line })}\n style={\n wrapText ? { whiteSpace: 'pre-wrap', wordBreak: 'break-all' } : undefined\n }\n >\n {line.map((token, key) => (\n <span key={key} {...getTokenProps({ token })} />\n ))}\n </div>\n ))}\n </div>\n </pre>\n {copyButton && (\n <div ref={buttonWrapperRef} className={buttonPositionClass}>\n {copyButton}\n </div>\n )}\n </div>\n )}\n </Highlight>\n );\n },\n);\n\nCodeBlockVanilla.displayName = 'CodeBlockVanilla';\n"],"names":["pre"],"mappings":"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"}