@stackone/malachite 2.50.0 → 2.51.1
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.
- package/dist/components/CodeBlock.js +105 -102
- package/dist/components/CodeBlock.js.map +1 -1
- package/dist/components/ConfirmationDialog.js +129 -154
- package/dist/components/ConfirmationDialog.js.map +1 -1
- package/dist/components/SelectableCard.js +36 -35
- package/dist/components/SelectableCard.js.map +1 -1
- package/dist/components/useClipboardCopy.js +38 -0
- package/dist/components/useClipboardCopy.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,111 +1,114 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
1
|
+
import { jsxs as C, jsx as e, Fragment as z } from "react/jsx-runtime";
|
|
2
|
+
import K from "@uiw/react-json-view";
|
|
3
3
|
import j from "react";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
4
|
+
import B from "./CustomIcons/CheckmarkIcon.js";
|
|
5
|
+
import E from "./CustomIcons/CopyIcon.js";
|
|
6
|
+
import { diffHunks as G } from "./codeBlockDiff.js";
|
|
7
|
+
import { CodeLine as M } from "./codeBlockLine.js";
|
|
8
|
+
import { FOCUS_RING_INSET as U, FOCUS_RING as H } from "./focusRing.js";
|
|
9
|
+
import { useClipboardCopy as P } from "./useClipboardCopy.js";
|
|
10
|
+
const _ = j.lazy(() => import("./CodeBlockHighlighter.js")), q = {
|
|
9
11
|
added: "var(--malachite-codeblock-diff-added-background)",
|
|
10
12
|
removed: "var(--malachite-codeblock-diff-removed-background)",
|
|
11
13
|
context: void 0
|
|
12
|
-
},
|
|
14
|
+
}, J = {
|
|
13
15
|
added: "+",
|
|
14
16
|
removed: "-",
|
|
15
17
|
context: void 0
|
|
16
|
-
},
|
|
18
|
+
}, V = {
|
|
17
19
|
added: "var(--malachite-codeblock-diff-assistant-background)",
|
|
18
20
|
removed: "var(--malachite-codeblock-diff-assistant-removed-background)",
|
|
19
21
|
context: void 0
|
|
20
|
-
},
|
|
22
|
+
}, W = {
|
|
21
23
|
added: "✦",
|
|
22
24
|
// U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.
|
|
23
25
|
removed: "−",
|
|
24
26
|
context: "·"
|
|
25
|
-
},
|
|
27
|
+
}, Q = {
|
|
26
28
|
added: "var(--malachite-codeblock-diff-assistant-foreground)",
|
|
27
29
|
removed: "var(--malachite-codeblock-diff-removed-foreground)",
|
|
28
30
|
context: "var(--malachite-codeblock-diff-context-foreground)"
|
|
29
|
-
},
|
|
30
|
-
const
|
|
31
|
+
}, X = (o) => `⋯ ${o} unchanged ${o === 1 ? "line" : "lines"}`, Y = (o, l, d) => {
|
|
32
|
+
const r = d === "assistant";
|
|
31
33
|
return {
|
|
32
|
-
background:
|
|
33
|
-
marker:
|
|
34
|
-
markerColor:
|
|
34
|
+
background: r ? V[o.type] : q[o.type],
|
|
35
|
+
marker: r ? W[o.type] : J[o.type],
|
|
36
|
+
markerColor: r ? Q[o.type] : void 0,
|
|
35
37
|
// Reserved on unchanged rows too, so the code column does not step in and out.
|
|
36
38
|
reserveMarker: !0,
|
|
37
39
|
// Context rows read as de-emphasised, not just unmarked, in the assistant palette.
|
|
38
|
-
textColor:
|
|
39
|
-
strikethrough:
|
|
40
|
-
separatorAbove: o.skippedAbove === void 0 ? void 0 :
|
|
40
|
+
textColor: r && o.type === "context" ? "var(--malachite-codeblock-diff-context-text)" : void 0,
|
|
41
|
+
strikethrough: r && o.type === "removed",
|
|
42
|
+
separatorAbove: o.skippedAbove === void 0 ? void 0 : X(o.skippedAbove),
|
|
41
43
|
// A removed line has no number in the after-text, so it keeps the one it had before.
|
|
42
|
-
lineNumber:
|
|
44
|
+
lineNumber: l ? o.afterNumber ?? o.beforeNumber : void 0
|
|
43
45
|
};
|
|
44
|
-
},
|
|
46
|
+
}, vo = ({
|
|
45
47
|
code: o,
|
|
46
|
-
json:
|
|
47
|
-
showLineNumbers:
|
|
48
|
-
className:
|
|
48
|
+
json: l,
|
|
49
|
+
showLineNumbers: d = !0,
|
|
50
|
+
className: r = "",
|
|
49
51
|
style: x = {},
|
|
50
|
-
height:
|
|
51
|
-
enableCopy:
|
|
52
|
-
wrapLines:
|
|
53
|
-
language:
|
|
54
|
-
collapsed:
|
|
55
|
-
diff:
|
|
56
|
-
"aria-label":
|
|
57
|
-
"aria-labelledby":
|
|
52
|
+
height: w,
|
|
53
|
+
enableCopy: k = !0,
|
|
54
|
+
wrapLines: h = !1,
|
|
55
|
+
language: m,
|
|
56
|
+
collapsed: R = !1,
|
|
57
|
+
diff: t,
|
|
58
|
+
"aria-label": S,
|
|
59
|
+
"aria-labelledby": N
|
|
58
60
|
}) => {
|
|
59
|
-
const
|
|
60
|
-
`)) ?? "",
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
61
|
+
const c = t ? G(t.before, t.after, t.context) : null, s = (c == null ? void 0 : c.map((i) => i.text).join(`
|
|
62
|
+
`)) ?? "", b = (() => {
|
|
63
|
+
if (c)
|
|
64
|
+
return s;
|
|
63
65
|
if (o)
|
|
64
66
|
return o;
|
|
65
|
-
if (
|
|
67
|
+
if (l !== void 0)
|
|
66
68
|
try {
|
|
67
|
-
return JSON.stringify(
|
|
69
|
+
return JSON.stringify(l, null, 2);
|
|
68
70
|
} catch {
|
|
69
71
|
return;
|
|
70
72
|
}
|
|
71
|
-
})(),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
73
|
+
})(), { outcome: T, copy: D } = P(b), A = T === "copied", F = k && b !== void 0 && /* @__PURE__ */ C(z, { children: [
|
|
74
|
+
/* @__PURE__ */ e(
|
|
75
|
+
"button",
|
|
76
|
+
{
|
|
77
|
+
type: "button",
|
|
78
|
+
"aria-label": "Copy",
|
|
79
|
+
onClick: () => {
|
|
80
|
+
b !== void 0 && D(b);
|
|
81
|
+
},
|
|
82
|
+
className: `absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${H}`,
|
|
83
|
+
style: { color: "var(--malachite-codeblock-line-number)" },
|
|
84
|
+
children: A ? /* @__PURE__ */ e(B, { size: 14 }) : /* @__PURE__ */ e(E, { size: 14 })
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ e("span", { "aria-live": "polite", className: "sr-only", children: A ? "Copied to clipboard" : "" })
|
|
88
|
+
] }), n = {
|
|
86
89
|
role: "region",
|
|
87
|
-
"aria-label":
|
|
88
|
-
"aria-labelledby":
|
|
90
|
+
"aria-label": N ? S : S ?? "Code",
|
|
91
|
+
"aria-labelledby": N,
|
|
89
92
|
tabIndex: 0,
|
|
90
|
-
className: `box-border h-full overflow-auto ${
|
|
93
|
+
className: `box-border h-full overflow-auto ${U}`
|
|
91
94
|
};
|
|
92
|
-
if (
|
|
93
|
-
return /* @__PURE__ */
|
|
95
|
+
if (l && !c)
|
|
96
|
+
return /* @__PURE__ */ C(
|
|
94
97
|
"div",
|
|
95
98
|
{
|
|
96
|
-
className: `relative border border-solid rounded-lg overflow-hidden ${
|
|
99
|
+
className: `relative border border-solid rounded-lg overflow-hidden ${r}`,
|
|
97
100
|
style: {
|
|
98
101
|
backgroundColor: "var(--malachite-codeblock-background)",
|
|
99
102
|
borderColor: "var(--malachite-codeblock-border)",
|
|
100
|
-
height:
|
|
103
|
+
height: w,
|
|
101
104
|
...x
|
|
102
105
|
},
|
|
103
106
|
children: [
|
|
104
|
-
|
|
105
|
-
/* @__PURE__ */ e("div", { ...
|
|
106
|
-
|
|
107
|
+
F,
|
|
108
|
+
/* @__PURE__ */ e("div", { ...n, children: /* @__PURE__ */ e(
|
|
109
|
+
K,
|
|
107
110
|
{
|
|
108
|
-
value:
|
|
111
|
+
value: l,
|
|
109
112
|
style: {
|
|
110
113
|
backgroundColor: "var(--malachite-codeblock-background)",
|
|
111
114
|
color: "var(--malachite-codeblock-foreground)",
|
|
@@ -141,32 +144,32 @@ const F = j.lazy(() => import("./CodeBlockHighlighter.js")), E = {
|
|
|
141
144
|
"--w-rjv-type-undefined-color": "var(--malachite-codeblock-comment)"
|
|
142
145
|
},
|
|
143
146
|
displayDataTypes: !1,
|
|
144
|
-
enableClipboard:
|
|
145
|
-
collapsed:
|
|
147
|
+
enableClipboard: k,
|
|
148
|
+
collapsed: R,
|
|
146
149
|
displayObjectSize: !1
|
|
147
150
|
}
|
|
148
151
|
) })
|
|
149
152
|
]
|
|
150
153
|
}
|
|
151
154
|
);
|
|
152
|
-
const p =
|
|
153
|
-
const y =
|
|
155
|
+
const p = k && (!!o || !!c), f = (i, a) => {
|
|
156
|
+
const y = i.split(`
|
|
154
157
|
`);
|
|
155
158
|
return /* @__PURE__ */ e(
|
|
156
159
|
"div",
|
|
157
160
|
{
|
|
158
|
-
...
|
|
159
|
-
className: `${
|
|
161
|
+
...n,
|
|
162
|
+
className: `${n.className} p-4 text-left`,
|
|
160
163
|
style: { paddingRight: p ? 44 : void 0 },
|
|
161
164
|
children: /* @__PURE__ */ e("div", { style: { width: "max-content", minWidth: "100%" }, children: y.map((v, g) => {
|
|
162
|
-
const
|
|
165
|
+
const u = a == null ? void 0 : a(g);
|
|
163
166
|
return /* @__PURE__ */ e(
|
|
164
|
-
|
|
167
|
+
M,
|
|
165
168
|
{
|
|
166
169
|
line: v,
|
|
167
|
-
lineNumber: (
|
|
168
|
-
wrap:
|
|
169
|
-
decoration:
|
|
170
|
+
lineNumber: (u == null ? void 0 : u.lineNumber) ?? (d ? g + 1 : void 0),
|
|
171
|
+
wrap: h,
|
|
172
|
+
decoration: u,
|
|
170
173
|
children: v
|
|
171
174
|
},
|
|
172
175
|
g
|
|
@@ -174,8 +177,8 @@ const F = j.lazy(() => import("./CodeBlockHighlighter.js")), E = {
|
|
|
174
177
|
}) })
|
|
175
178
|
}
|
|
176
179
|
);
|
|
177
|
-
},
|
|
178
|
-
if (
|
|
180
|
+
}, I = () => o ? f(o) : null, O = (i) => {
|
|
181
|
+
if (i.length === 0)
|
|
179
182
|
return /* @__PURE__ */ e(
|
|
180
183
|
"div",
|
|
181
184
|
{
|
|
@@ -184,51 +187,51 @@ const F = j.lazy(() => import("./CodeBlockHighlighter.js")), E = {
|
|
|
184
187
|
children: "No changes"
|
|
185
188
|
}
|
|
186
189
|
);
|
|
187
|
-
const
|
|
188
|
-
const v =
|
|
189
|
-
return v ?
|
|
190
|
+
const a = (y) => {
|
|
191
|
+
const v = i[y];
|
|
192
|
+
return v ? Y(v, d, t == null ? void 0 : t.origin) : void 0;
|
|
190
193
|
};
|
|
191
|
-
return
|
|
192
|
-
|
|
194
|
+
return m ? /* @__PURE__ */ e(j.Suspense, { fallback: f(s, a), children: /* @__PURE__ */ e(
|
|
195
|
+
_,
|
|
193
196
|
{
|
|
194
|
-
code:
|
|
195
|
-
language:
|
|
196
|
-
showLineNumbers:
|
|
197
|
-
wrapLines:
|
|
197
|
+
code: s,
|
|
198
|
+
language: m,
|
|
199
|
+
showLineNumbers: d,
|
|
200
|
+
wrapLines: h,
|
|
198
201
|
copyClearance: p,
|
|
199
|
-
decorate:
|
|
200
|
-
viewportProps:
|
|
202
|
+
decorate: a,
|
|
203
|
+
viewportProps: n
|
|
201
204
|
}
|
|
202
|
-
) }) : f(
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
+
) }) : f(s, a);
|
|
206
|
+
}, $ = () => o ? m ? /* @__PURE__ */ e(j.Suspense, { fallback: I(), children: /* @__PURE__ */ e(
|
|
207
|
+
_,
|
|
205
208
|
{
|
|
206
209
|
code: o,
|
|
207
|
-
language:
|
|
208
|
-
showLineNumbers:
|
|
209
|
-
wrapLines:
|
|
210
|
+
language: m,
|
|
211
|
+
showLineNumbers: d,
|
|
212
|
+
wrapLines: h,
|
|
210
213
|
copyClearance: p,
|
|
211
|
-
viewportProps:
|
|
214
|
+
viewportProps: n
|
|
212
215
|
}
|
|
213
|
-
) }) :
|
|
214
|
-
return /* @__PURE__ */
|
|
216
|
+
) }) : I() : null;
|
|
217
|
+
return /* @__PURE__ */ C(
|
|
215
218
|
"div",
|
|
216
219
|
{
|
|
217
|
-
className: `relative border border-solid rounded-lg overflow-hidden ${
|
|
220
|
+
className: `relative border border-solid rounded-lg overflow-hidden ${r}`,
|
|
218
221
|
style: {
|
|
219
222
|
backgroundColor: "var(--malachite-codeblock-background)",
|
|
220
223
|
borderColor: "var(--malachite-codeblock-border)",
|
|
221
|
-
height:
|
|
224
|
+
height: w,
|
|
222
225
|
...x
|
|
223
226
|
},
|
|
224
227
|
children: [
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
F,
|
|
229
|
+
c ? O(c) : $()
|
|
227
230
|
]
|
|
228
231
|
}
|
|
229
232
|
);
|
|
230
233
|
};
|
|
231
234
|
export {
|
|
232
|
-
|
|
235
|
+
vo as default
|
|
233
236
|
};
|
|
234
237
|
//# sourceMappingURL=CodeBlock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlock.js","sources":["../../src/components/CodeBlock.tsx"],"sourcesContent":["import JsonView from '@uiw/react-json-view';\nimport React from 'react';\nimport CopyIcon from './CustomIcons/CopyIcon';\nimport { type DiffDisplayRow, type DiffRowType, diffHunks } from './codeBlockDiff';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { FOCUS_RING, FOCUS_RING_INSET } from './focusRing';\n\nconst CodeBlockHighlighter = React.lazy(() => import('./CodeBlockHighlighter'));\n\nexport interface CodeBlockProps {\n /** The code content to display */\n code?: string;\n /** JSON object to display as formatted JSON */\n json?: object;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Custom class name */\n className?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Height of the code block */\n height?: string | number;\n /** Enable copy functionality */\n enableCopy?: boolean;\n /** Wrap long lines instead of scrolling horizontally */\n wrapLines?: boolean;\n /**\n * Highlight the code with this language's grammar. `cedar` is a grammar this library\n * ships itself (`prismCedar.ts`), since Prism and refractor carry none; widen the union\n * as further grammars are registered in CodeBlockHighlighter.\n */\n language?: 'yaml' | 'cedar';\n /** How much of a `json` tree starts collapsed: `true` all of it, a number below that depth. */\n collapsed?: boolean | number;\n /**\n * Renders the change between two texts rather than one text, and takes precedence over\n * `code` and `json`. Only the changed lines are shown, with `context` unchanged ones either\n * side, so a small edit to a long document reads as a few hunks instead of the whole thing.\n */\n diff?: {\n before: string;\n after: string;\n /** Unchanged lines kept either side of each change. Three by convention. */\n context?: number;\n /**\n * Swaps the `+`/`-` gutter and tinted rows for the palette a mock specified for\n * AI-authored changes: star, minus-sign and middle-dot markers, and a struck-through\n * removal. Omit to keep the neutral markers; there is no default consumer for the\n * assistant look yet.\n */\n origin?: 'assistant';\n };\n /** Names the scrollable region. Defaults to \"Code\". */\n 'aria-label'?: string;\n /** Names the scrollable region by a visible label instead of `aria-label`. */\n 'aria-labelledby'?: string;\n}\n\nconst DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-added-background)',\n removed: 'var(--malachite-codeblock-diff-removed-background)',\n context: undefined,\n};\n\nconst DIFF_MARKERS: Record<DiffRowType, string | undefined> = {\n added: '+',\n removed: '-',\n context: undefined,\n};\n\n// The assistant palette also marks context rows, which the neutral one leaves bare.\nconst ASSISTANT_DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-assistant-background)',\n removed: 'var(--malachite-codeblock-diff-assistant-removed-background)',\n context: undefined,\n};\n\nconst ASSISTANT_DIFF_MARKERS: Record<DiffRowType, string> = {\n added: '\\u2726',\n // U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.\n removed: '\\u2212',\n context: '\\u00b7',\n};\n\nconst ASSISTANT_DIFF_MARKER_COLORS: Record<DiffRowType, string> = {\n added: 'var(--malachite-codeblock-diff-assistant-foreground)',\n removed: 'var(--malachite-codeblock-diff-removed-foreground)',\n context: 'var(--malachite-codeblock-diff-context-foreground)',\n};\n\nconst unchangedRun = (count: number): string =>\n `\\u22ef ${count} unchanged ${count === 1 ? 'line' : 'lines'}`;\n\nconst diffDecoration = (\n row: DiffDisplayRow,\n showLineNumbers: boolean,\n origin?: 'assistant',\n): CodeLineDecoration => {\n const assistant = origin === 'assistant';\n\n return {\n background: assistant ? ASSISTANT_DIFF_BACKGROUNDS[row.type] : DIFF_BACKGROUNDS[row.type],\n marker: assistant ? ASSISTANT_DIFF_MARKERS[row.type] : DIFF_MARKERS[row.type],\n markerColor: assistant ? ASSISTANT_DIFF_MARKER_COLORS[row.type] : undefined,\n // Reserved on unchanged rows too, so the code column does not step in and out.\n reserveMarker: true,\n // Context rows read as de-emphasised, not just unmarked, in the assistant palette.\n textColor:\n assistant && row.type === 'context'\n ? 'var(--malachite-codeblock-diff-context-text)'\n : undefined,\n strikethrough: assistant && row.type === 'removed',\n separatorAbove: row.skippedAbove === undefined ? undefined : unchangedRun(row.skippedAbove),\n // A removed line has no number in the after-text, so it keeps the one it had before.\n lineNumber: showLineNumbers ? (row.afterNumber ?? row.beforeNumber) : undefined,\n };\n};\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n json,\n showLineNumbers = true,\n className = '',\n style = {},\n height,\n enableCopy = true,\n wrapLines = false,\n language,\n collapsed = false,\n diff,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const diffRows = diff ? diffHunks(diff.before, diff.after, diff.context) : null;\n const diffText = diffRows?.map((row) => row.text).join('\\n') ?? '';\n\n /**\n * What the button puts on the clipboard, in the same form the block is showing. A JSON\n * block is pretty-printed rather than handed over minified: the reader is copying what\n * they can see. `undefined` means there is nothing to copy and no button to offer.\n */\n const copyText = (): string | undefined => {\n if (diffRows) {\n return diffText;\n }\n\n // An empty block has nothing to copy, so it offers no button — `!== undefined` would\n // hand back the empty string and put a dead control on it.\n if (code) {\n return code;\n }\n\n if (json !== undefined) {\n try {\n return JSON.stringify(json, null, 2);\n } catch {\n // A cycle or a BigInt: no honest text to copy, so offer no button.\n return undefined;\n }\n }\n\n return undefined;\n };\n\n const textToCopy = copyText();\n\n // `?.` no-ops when the clipboard API is absent (insecure context); `.catch` swallows a rejection.\n const handleCopy = () => {\n if (textToCopy === undefined) {\n return;\n }\n\n navigator.clipboard?.writeText(textToCopy)?.catch(() => undefined);\n };\n\n // Declared once and rendered by both the JSON branch and the code branch below, so the\n // two tabs of one document do not disagree about whether it can be copied.\n const copyButton = enableCopy && textToCopy !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Copy\"\n onClick={handleCopy}\n className={`absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${FOCUS_RING}`}\n style={{ color: 'var(--malachite-codeblock-line-number)' }}\n >\n <CopyIcon size={14} />\n </button>\n );\n\n // Tabbable so a keyboard can scroll it: Safari never focuses a scroll container on its own.\n const viewportProps = {\n role: 'region',\n 'aria-label': ariaLabelledBy ? ariaLabel : (ariaLabel ?? 'Code'),\n 'aria-labelledby': ariaLabelledBy,\n tabIndex: 0,\n className: `box-border h-full overflow-auto ${FOCUS_RING_INSET}`,\n } satisfies React.HTMLAttributes<HTMLElement>;\n\n // If JSON is provided, use JsonView component\n if (json && !diffRows) {\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {/* The frame clips at `height`; this scrolls inside it, so the copy button stays put. */}\n <div {...viewportProps}>\n <JsonView\n value={json}\n style={\n {\n backgroundColor: 'var(--malachite-codeblock-background)',\n color: 'var(--malachite-codeblock-foreground)',\n fontSize: '14px',\n fontFamily: 'var(--malachite-font-mono, monospace)',\n padding: '16px',\n lineHeight: '1.5',\n textAlign: 'left',\n '--w-rjv-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-key-string': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-background-color': 'var(--malachite-codeblock-background)',\n '--w-rjv-line-color': 'var(--malachite-codeblock-border)',\n '--w-rjv-arrow-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-edit-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-info-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-update-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-copied-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-copied-success-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-curlybraces-color':\n 'var(--malachite-codeblock-foreground)',\n '--w-rjv-colon-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-brackets-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-quotes-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-quotes-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-int-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-float-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-bigint-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-boolean-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-date-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-url-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-null-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-nan-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-undefined-color':\n 'var(--malachite-codeblock-comment)',\n } as React.CSSProperties\n }\n displayDataTypes={false}\n enableClipboard={enableCopy}\n collapsed={collapsed}\n displayObjectSize={false}\n />\n </div>\n </div>\n );\n }\n\n // Reserve clearance so a wide first line never sits under the floating copy button.\n const copyClearance = enableCopy && (!!code || !!diffRows);\n\n const renderPlainLines = (\n text: string,\n decorate?: (index: number) => CodeLineDecoration | undefined,\n ) => {\n const lines = text.split('\\n');\n\n return (\n <div\n {...viewportProps}\n className={`${viewportProps.className} p-4 text-left`}\n style={{ paddingRight: copyClearance ? 44 : undefined }}\n >\n {/* As wide as the widest line, floored at the view, so rows filling it end level. */}\n <div style={{ width: 'max-content', minWidth: '100%' }}>\n {lines.map((line, index) => {\n const decoration = decorate?.(index);\n\n return (\n <CodeLine\n key={index}\n line={line}\n lineNumber={\n decoration?.lineNumber ??\n (showLineNumbers ? index + 1 : undefined)\n }\n wrap={wrapLines}\n decoration={decoration}\n >\n {line}\n </CodeLine>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderPlainCode = () => (code ? renderPlainLines(code) : null);\n\n const renderDiff = (rows: DiffDisplayRow[]) => {\n if (rows.length === 0) {\n return (\n <div\n className=\"p-4 text-left\"\n style={{ color: 'var(--malachite-codeblock-comment)' }}\n >\n No changes\n </div>\n );\n }\n\n const decorate = (index: number) => {\n const row = rows[index];\n\n return row ? diffDecoration(row, showLineNumbers, diff?.origin) : undefined;\n };\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainLines(diffText, decorate)}>\n {/*\n * The whole merged text goes to the highlighter in one piece, so a hunk\n * is tokenised in the company of its neighbours rather than on its own.\n * Prism still cannot see the lines the hunks left out, so a construct\n * spanning an omitted run can highlight oddly — the reason `context`\n * defaults to a few lines rather than none.\n */}\n <CodeBlockHighlighter\n code={diffText}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n decorate={decorate}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainLines(diffText, decorate);\n };\n\n // For code strings, create a simple syntax-highlighted view\n const renderCodeContent = () => {\n if (!code) {\n return null;\n }\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainCode()}>\n <CodeBlockHighlighter\n code={code}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainCode();\n };\n\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {diffRows ? renderDiff(diffRows) : renderCodeContent()}\n </div>\n );\n};\n\nexport default CodeBlock;\n"],"names":["CodeBlockHighlighter","React","DIFF_BACKGROUNDS","DIFF_MARKERS","ASSISTANT_DIFF_BACKGROUNDS","ASSISTANT_DIFF_MARKERS","ASSISTANT_DIFF_MARKER_COLORS","unchangedRun","count","diffDecoration","row","showLineNumbers","origin","assistant","CodeBlock","code","json","className","style","height","enableCopy","wrapLines","language","collapsed","diff","ariaLabel","ariaLabelledBy","diffRows","diffHunks","diffText","textToCopy","copyButton","jsx","_b","_a","FOCUS_RING","CopyIcon","viewportProps","FOCUS_RING_INSET","jsxs","JsonView","copyClearance","renderPlainLines","text","decorate","lines","line","index","decoration","CodeLine","renderPlainCode","renderDiff","rows","renderCodeContent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeBlock.js","sources":["../../src/components/CodeBlock.tsx"],"sourcesContent":["import JsonView from '@uiw/react-json-view';\nimport React from 'react';\nimport CheckmarkIcon from './CustomIcons/CheckmarkIcon';\nimport CopyIcon from './CustomIcons/CopyIcon';\nimport { type DiffDisplayRow, type DiffRowType, diffHunks } from './codeBlockDiff';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { FOCUS_RING, FOCUS_RING_INSET } from './focusRing';\nimport { useClipboardCopy } from './useClipboardCopy';\n\nconst CodeBlockHighlighter = React.lazy(() => import('./CodeBlockHighlighter'));\n\nexport interface CodeBlockProps {\n /** The code content to display */\n code?: string;\n /** JSON object to display as formatted JSON */\n json?: object;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Custom class name */\n className?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Height of the code block */\n height?: string | number;\n /** Enable copy functionality */\n enableCopy?: boolean;\n /** Wrap long lines instead of scrolling horizontally */\n wrapLines?: boolean;\n /**\n * Highlight the code with this language's grammar. `cedar` is a grammar this library\n * ships itself (`prismCedar.ts`), since Prism and refractor carry none; widen the union\n * as further grammars are registered in CodeBlockHighlighter.\n */\n language?: 'yaml' | 'cedar';\n /** How much of a `json` tree starts collapsed: `true` all of it, a number below that depth. */\n collapsed?: boolean | number;\n /**\n * Renders the change between two texts rather than one text, and takes precedence over\n * `code` and `json`. Only the changed lines are shown, with `context` unchanged ones either\n * side, so a small edit to a long document reads as a few hunks instead of the whole thing.\n */\n diff?: {\n before: string;\n after: string;\n /** Unchanged lines kept either side of each change. Three by convention. */\n context?: number;\n /**\n * Swaps the `+`/`-` gutter and tinted rows for the palette a mock specified for\n * AI-authored changes: star, minus-sign and middle-dot markers, and a struck-through\n * removal. Omit to keep the neutral markers; there is no default consumer for the\n * assistant look yet.\n */\n origin?: 'assistant';\n };\n /** Names the scrollable region. Defaults to \"Code\". */\n 'aria-label'?: string;\n /** Names the scrollable region by a visible label instead of `aria-label`. */\n 'aria-labelledby'?: string;\n}\n\nconst DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-added-background)',\n removed: 'var(--malachite-codeblock-diff-removed-background)',\n context: undefined,\n};\n\nconst DIFF_MARKERS: Record<DiffRowType, string | undefined> = {\n added: '+',\n removed: '-',\n context: undefined,\n};\n\n// The assistant palette also marks context rows, which the neutral one leaves bare.\nconst ASSISTANT_DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-assistant-background)',\n removed: 'var(--malachite-codeblock-diff-assistant-removed-background)',\n context: undefined,\n};\n\nconst ASSISTANT_DIFF_MARKERS: Record<DiffRowType, string> = {\n added: '\\u2726',\n // U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.\n removed: '\\u2212',\n context: '\\u00b7',\n};\n\nconst ASSISTANT_DIFF_MARKER_COLORS: Record<DiffRowType, string> = {\n added: 'var(--malachite-codeblock-diff-assistant-foreground)',\n removed: 'var(--malachite-codeblock-diff-removed-foreground)',\n context: 'var(--malachite-codeblock-diff-context-foreground)',\n};\n\nconst unchangedRun = (count: number): string =>\n `\\u22ef ${count} unchanged ${count === 1 ? 'line' : 'lines'}`;\n\nconst diffDecoration = (\n row: DiffDisplayRow,\n showLineNumbers: boolean,\n origin?: 'assistant',\n): CodeLineDecoration => {\n const assistant = origin === 'assistant';\n\n return {\n background: assistant ? ASSISTANT_DIFF_BACKGROUNDS[row.type] : DIFF_BACKGROUNDS[row.type],\n marker: assistant ? ASSISTANT_DIFF_MARKERS[row.type] : DIFF_MARKERS[row.type],\n markerColor: assistant ? ASSISTANT_DIFF_MARKER_COLORS[row.type] : undefined,\n // Reserved on unchanged rows too, so the code column does not step in and out.\n reserveMarker: true,\n // Context rows read as de-emphasised, not just unmarked, in the assistant palette.\n textColor:\n assistant && row.type === 'context'\n ? 'var(--malachite-codeblock-diff-context-text)'\n : undefined,\n strikethrough: assistant && row.type === 'removed',\n separatorAbove: row.skippedAbove === undefined ? undefined : unchangedRun(row.skippedAbove),\n // A removed line has no number in the after-text, so it keeps the one it had before.\n lineNumber: showLineNumbers ? (row.afterNumber ?? row.beforeNumber) : undefined,\n };\n};\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n json,\n showLineNumbers = true,\n className = '',\n style = {},\n height,\n enableCopy = true,\n wrapLines = false,\n language,\n collapsed = false,\n diff,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const diffRows = diff ? diffHunks(diff.before, diff.after, diff.context) : null;\n const diffText = diffRows?.map((row) => row.text).join('\\n') ?? '';\n\n /**\n * What the button puts on the clipboard, in the same form the block is showing. A JSON\n * block is pretty-printed rather than handed over minified: the reader is copying what\n * they can see. `undefined` means there is nothing to copy and no button to offer.\n */\n const copyText = (): string | undefined => {\n if (diffRows) {\n return diffText;\n }\n\n // An empty block has nothing to copy, so it offers no button — `!== undefined` would\n // hand back the empty string and put a dead control on it.\n if (code) {\n return code;\n }\n\n if (json !== undefined) {\n try {\n return JSON.stringify(json, null, 2);\n } catch {\n // A cycle or a BigInt: no honest text to copy, so offer no button.\n return undefined;\n }\n }\n\n return undefined;\n };\n\n const textToCopy = copyText();\n\n const { outcome: copyOutcome, copy } = useClipboardCopy(textToCopy);\n const copied = copyOutcome === 'copied';\n\n const handleCopy = () => {\n if (textToCopy !== undefined) {\n void copy(textToCopy);\n }\n };\n\n // Declared once and rendered by both the JSON branch and the code branch below, so the\n // two tabs of one document do not disagree about whether it can be copied.\n const copyButton = enableCopy && textToCopy !== undefined && (\n <>\n <button\n type=\"button\"\n aria-label=\"Copy\"\n onClick={handleCopy}\n className={`absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${FOCUS_RING}`}\n style={{ color: 'var(--malachite-codeblock-line-number)' }}\n >\n {copied ? <CheckmarkIcon size={14} /> : <CopyIcon size={14} />}\n </button>\n {/* Not role=\"status\": one per block would collide with a page's own status queries. */}\n <span aria-live=\"polite\" className=\"sr-only\">\n {copied ? 'Copied to clipboard' : ''}\n </span>\n </>\n );\n\n // Tabbable so a keyboard can scroll it: Safari never focuses a scroll container on its own.\n const viewportProps = {\n role: 'region',\n 'aria-label': ariaLabelledBy ? ariaLabel : (ariaLabel ?? 'Code'),\n 'aria-labelledby': ariaLabelledBy,\n tabIndex: 0,\n className: `box-border h-full overflow-auto ${FOCUS_RING_INSET}`,\n } satisfies React.HTMLAttributes<HTMLElement>;\n\n // If JSON is provided, use JsonView component\n if (json && !diffRows) {\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {/* The frame clips at `height`; this scrolls inside it, so the copy button stays put. */}\n <div {...viewportProps}>\n <JsonView\n value={json}\n style={\n {\n backgroundColor: 'var(--malachite-codeblock-background)',\n color: 'var(--malachite-codeblock-foreground)',\n fontSize: '14px',\n fontFamily: 'var(--malachite-font-mono, monospace)',\n padding: '16px',\n lineHeight: '1.5',\n textAlign: 'left',\n '--w-rjv-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-key-string': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-background-color': 'var(--malachite-codeblock-background)',\n '--w-rjv-line-color': 'var(--malachite-codeblock-border)',\n '--w-rjv-arrow-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-edit-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-info-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-update-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-copied-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-copied-success-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-curlybraces-color':\n 'var(--malachite-codeblock-foreground)',\n '--w-rjv-colon-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-brackets-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-quotes-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-quotes-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-int-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-float-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-bigint-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-boolean-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-date-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-url-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-null-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-nan-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-undefined-color':\n 'var(--malachite-codeblock-comment)',\n } as React.CSSProperties\n }\n displayDataTypes={false}\n enableClipboard={enableCopy}\n collapsed={collapsed}\n displayObjectSize={false}\n />\n </div>\n </div>\n );\n }\n\n // Reserve clearance so a wide first line never sits under the floating copy button.\n const copyClearance = enableCopy && (!!code || !!diffRows);\n\n const renderPlainLines = (\n text: string,\n decorate?: (index: number) => CodeLineDecoration | undefined,\n ) => {\n const lines = text.split('\\n');\n\n return (\n <div\n {...viewportProps}\n className={`${viewportProps.className} p-4 text-left`}\n style={{ paddingRight: copyClearance ? 44 : undefined }}\n >\n {/* As wide as the widest line, floored at the view, so rows filling it end level. */}\n <div style={{ width: 'max-content', minWidth: '100%' }}>\n {lines.map((line, index) => {\n const decoration = decorate?.(index);\n\n return (\n <CodeLine\n key={index}\n line={line}\n lineNumber={\n decoration?.lineNumber ??\n (showLineNumbers ? index + 1 : undefined)\n }\n wrap={wrapLines}\n decoration={decoration}\n >\n {line}\n </CodeLine>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderPlainCode = () => (code ? renderPlainLines(code) : null);\n\n const renderDiff = (rows: DiffDisplayRow[]) => {\n if (rows.length === 0) {\n return (\n <div\n className=\"p-4 text-left\"\n style={{ color: 'var(--malachite-codeblock-comment)' }}\n >\n No changes\n </div>\n );\n }\n\n const decorate = (index: number) => {\n const row = rows[index];\n\n return row ? diffDecoration(row, showLineNumbers, diff?.origin) : undefined;\n };\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainLines(diffText, decorate)}>\n {/*\n * The whole merged text goes to the highlighter in one piece, so a hunk\n * is tokenised in the company of its neighbours rather than on its own.\n * Prism still cannot see the lines the hunks left out, so a construct\n * spanning an omitted run can highlight oddly — the reason `context`\n * defaults to a few lines rather than none.\n */}\n <CodeBlockHighlighter\n code={diffText}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n decorate={decorate}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainLines(diffText, decorate);\n };\n\n // For code strings, create a simple syntax-highlighted view\n const renderCodeContent = () => {\n if (!code) {\n return null;\n }\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainCode()}>\n <CodeBlockHighlighter\n code={code}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainCode();\n };\n\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {diffRows ? renderDiff(diffRows) : renderCodeContent()}\n </div>\n );\n};\n\nexport default CodeBlock;\n"],"names":["CodeBlockHighlighter","React","DIFF_BACKGROUNDS","DIFF_MARKERS","ASSISTANT_DIFF_BACKGROUNDS","ASSISTANT_DIFF_MARKERS","ASSISTANT_DIFF_MARKER_COLORS","unchangedRun","count","diffDecoration","row","showLineNumbers","origin","assistant","CodeBlock","code","json","className","style","height","enableCopy","wrapLines","language","collapsed","diff","ariaLabel","ariaLabelledBy","diffRows","diffHunks","diffText","textToCopy","copyOutcome","copy","useClipboardCopy","copied","copyButton","jsxs","Fragment","jsx","FOCUS_RING","CheckmarkIcon","CopyIcon","viewportProps","FOCUS_RING_INSET","JsonView","copyClearance","renderPlainLines","text","decorate","lines","line","index","decoration","CodeLine","renderPlainCode","renderDiff","rows","renderCodeContent"],"mappings":"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"}
|