@fragments-sdk/ui 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/assets/ui.css +443 -247
  2. package/dist/blocks/components/index.d.ts +0 -2
  3. package/dist/blocks/components/index.d.ts.map +1 -1
  4. package/dist/codeblock.cjs +187 -184
  5. package/dist/codeblock.cjs.map +1 -1
  6. package/dist/codeblock.js +183 -180
  7. package/dist/codeblock.js.map +1 -1
  8. package/dist/components/Box/Box.module.scss.cjs +73 -0
  9. package/dist/components/Box/Box.module.scss.cjs.map +1 -1
  10. package/dist/components/Box/Box.module.scss.js +73 -0
  11. package/dist/components/Box/Box.module.scss.js.map +1 -1
  12. package/dist/components/ButtonGroup/ButtonGroup.module.scss.cjs +6 -0
  13. package/dist/components/ButtonGroup/ButtonGroup.module.scss.cjs.map +1 -1
  14. package/dist/components/ButtonGroup/ButtonGroup.module.scss.js +6 -0
  15. package/dist/components/ButtonGroup/ButtonGroup.module.scss.js.map +1 -1
  16. package/dist/components/CodeBlock/CodeBlock.module.scss.cjs +20 -23
  17. package/dist/components/CodeBlock/CodeBlock.module.scss.cjs.map +1 -1
  18. package/dist/components/CodeBlock/CodeBlock.module.scss.js +20 -23
  19. package/dist/components/CodeBlock/CodeBlock.module.scss.js.map +1 -1
  20. package/dist/components/CodeBlock/index.d.ts +11 -7
  21. package/dist/components/CodeBlock/index.d.ts.map +1 -1
  22. package/dist/components/Combobox/Combobox.module.scss.cjs +15 -15
  23. package/dist/components/Combobox/Combobox.module.scss.js +15 -15
  24. package/dist/components/DataTable/DataTable.module.scss.cjs +84 -0
  25. package/dist/components/DataTable/DataTable.module.scss.cjs.map +1 -0
  26. package/dist/components/DataTable/DataTable.module.scss.js +84 -0
  27. package/dist/components/DataTable/DataTable.module.scss.js.map +1 -0
  28. package/dist/components/DataTable/index.cjs +383 -0
  29. package/dist/components/DataTable/index.cjs.map +1 -0
  30. package/dist/components/DataTable/index.d.ts +78 -0
  31. package/dist/components/DataTable/index.d.ts.map +1 -0
  32. package/dist/components/DataTable/index.js +366 -0
  33. package/dist/components/DataTable/index.js.map +1 -0
  34. package/dist/components/Drawer/Drawer.module.scss.cjs +9 -0
  35. package/dist/components/Drawer/Drawer.module.scss.cjs.map +1 -1
  36. package/dist/components/Drawer/Drawer.module.scss.js +9 -0
  37. package/dist/components/Drawer/Drawer.module.scss.js.map +1 -1
  38. package/dist/components/Image/Image.module.scss.cjs +12 -0
  39. package/dist/components/Image/Image.module.scss.cjs.map +1 -1
  40. package/dist/components/Image/Image.module.scss.js +12 -0
  41. package/dist/components/Image/Image.module.scss.js.map +1 -1
  42. package/dist/components/Link/Link.module.scss.cjs +3 -0
  43. package/dist/components/Link/Link.module.scss.cjs.map +1 -1
  44. package/dist/components/Link/Link.module.scss.js +3 -0
  45. package/dist/components/Link/Link.module.scss.js.map +1 -1
  46. package/dist/components/List/List.module.scss.cjs +5 -0
  47. package/dist/components/List/List.module.scss.cjs.map +1 -1
  48. package/dist/components/List/List.module.scss.js +5 -0
  49. package/dist/components/List/List.module.scss.js.map +1 -1
  50. package/dist/components/Loading/Loading.module.scss.cjs +5 -0
  51. package/dist/components/Loading/Loading.module.scss.cjs.map +1 -1
  52. package/dist/components/Loading/Loading.module.scss.js +5 -0
  53. package/dist/components/Loading/Loading.module.scss.js.map +1 -1
  54. package/dist/components/Markdown/Markdown.module.scss.cjs +1 -1
  55. package/dist/components/Markdown/Markdown.module.scss.js +1 -1
  56. package/dist/components/Message/Message.module.scss.cjs +22 -16
  57. package/dist/components/Message/Message.module.scss.cjs.map +1 -1
  58. package/dist/components/Message/Message.module.scss.js +22 -16
  59. package/dist/components/Message/Message.module.scss.js.map +1 -1
  60. package/dist/components/Message/index.cjs +5 -3
  61. package/dist/components/Message/index.cjs.map +1 -1
  62. package/dist/components/Message/index.d.ts +5 -1
  63. package/dist/components/Message/index.d.ts.map +1 -1
  64. package/dist/components/Message/index.js +5 -3
  65. package/dist/components/Message/index.js.map +1 -1
  66. package/dist/components/Skeleton/Skeleton.module.scss.cjs +14 -0
  67. package/dist/components/Skeleton/Skeleton.module.scss.cjs.map +1 -1
  68. package/dist/components/Skeleton/Skeleton.module.scss.js +14 -0
  69. package/dist/components/Skeleton/Skeleton.module.scss.js.map +1 -1
  70. package/dist/components/Stack/Stack.module.scss.cjs +14 -0
  71. package/dist/components/Stack/Stack.module.scss.cjs.map +1 -1
  72. package/dist/components/Stack/Stack.module.scss.js +14 -0
  73. package/dist/components/Stack/Stack.module.scss.js.map +1 -1
  74. package/dist/components/Table/Table.module.scss.cjs +21 -36
  75. package/dist/components/Table/Table.module.scss.cjs.map +1 -1
  76. package/dist/components/Table/Table.module.scss.js +21 -36
  77. package/dist/components/Table/Table.module.scss.js.map +1 -1
  78. package/dist/components/Table/index.d.ts +35 -55
  79. package/dist/components/Table/index.d.ts.map +1 -1
  80. package/dist/components/Text/Text.module.scss.cjs +14 -0
  81. package/dist/components/Text/Text.module.scss.cjs.map +1 -1
  82. package/dist/components/Text/Text.module.scss.js +14 -0
  83. package/dist/components/Text/Text.module.scss.js.map +1 -1
  84. package/dist/components/Textarea/Textarea.module.scss.cjs +4 -0
  85. package/dist/components/Textarea/Textarea.module.scss.cjs.map +1 -1
  86. package/dist/components/Textarea/Textarea.module.scss.js +4 -0
  87. package/dist/components/Textarea/Textarea.module.scss.js.map +1 -1
  88. package/dist/components/ToggleGroup/ToggleGroup.module.scss.cjs +5 -0
  89. package/dist/components/ToggleGroup/ToggleGroup.module.scss.cjs.map +1 -1
  90. package/dist/components/ToggleGroup/ToggleGroup.module.scss.js +5 -0
  91. package/dist/components/ToggleGroup/ToggleGroup.module.scss.js.map +1 -1
  92. package/dist/index.cjs +119 -117
  93. package/dist/index.cjs.map +1 -1
  94. package/dist/index.d.ts +2 -1
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +3 -1
  97. package/dist/index.js.map +1 -1
  98. package/dist/table.cjs +44 -262
  99. package/dist/table.cjs.map +1 -1
  100. package/dist/table.js +47 -248
  101. package/dist/table.js.map +1 -1
  102. package/fragments.json +1 -1
  103. package/package.json +110 -118
  104. package/src/blocks/components/index.ts +0 -3
  105. package/src/components/CodeBlock/CodeBlock.module.scss +16 -34
  106. package/src/components/CodeBlock/index.tsx +351 -345
  107. package/src/components/Combobox/Combobox.module.scss +13 -9
  108. package/src/components/ConversationList/ConversationList.fragment.tsx +96 -129
  109. package/src/components/DataTable/DataTable.fragment.tsx +754 -0
  110. package/src/components/DataTable/DataTable.module.scss +300 -0
  111. package/src/components/DataTable/DataTable.test.tsx +224 -0
  112. package/src/components/DataTable/index.tsx +533 -0
  113. package/src/components/Message/Message.fragment.tsx +34 -0
  114. package/src/components/Message/Message.module.scss +11 -0
  115. package/src/components/Message/index.tsx +12 -3
  116. package/src/components/Table/Table.fragment.tsx +190 -175
  117. package/src/components/Table/Table.module.scss +15 -88
  118. package/src/components/Table/Table.test.tsx +184 -94
  119. package/src/components/Table/index.tsx +105 -374
  120. package/src/index.ts +15 -4
  121. package/src/tokens/_computed.scss +7 -6
  122. package/src/tokens/_density.scss +87 -47
  123. package/src/tokens/_variables.scss +46 -31
  124. package/dist/blocks/components/DataTable.d.ts +0 -19
  125. package/dist/blocks/components/DataTable.d.ts.map +0 -1
  126. package/src/blocks/components/DataTable.tsx +0 -124
package/dist/codeblock.js CHANGED
@@ -2,7 +2,6 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { useState, useMemo, useEffect, useCallback } from "react";
4
4
  import { TabsRoot, TabsList, Tab, TabsPanel } from "./components/Tabs/index.js";
5
- import { Button } from "./components/Button/index.js";
6
5
  import styles from "./components/CodeBlock/CodeBlock.module.scss.js";
7
6
  /* empty css */
8
7
  let _codeToHtml = null;
@@ -311,197 +310,199 @@ function processShikiHtml(html, options) {
311
310
  }
312
311
  return `<span class="${lineClass}">${line}</span>`;
313
312
  });
314
- return html.replace(
315
- /<code[^>]*>[\s\S]*?<\/code>/,
316
- `<code>${processedLines.join("\n")}</code>`
317
- );
313
+ return html.replace(/<code[^>]*>[\s\S]*?<\/code>/, `<code>${processedLines.join("\n")}</code>`);
318
314
  }
319
- const CodeBlockBase = React.forwardRef(
320
- function CodeBlock2({
321
- code,
322
- language = "tsx",
323
- theme = "one-dark-pro",
324
- showCopy = true,
325
- title,
326
- filename,
327
- caption,
328
- showLineNumbers = false,
329
- startLineNumber = 1,
330
- highlightLines,
331
- addedLines,
332
- removedLines,
333
- wordWrap = false,
334
- maxHeight,
335
- collapsible = false,
336
- defaultCollapsed = false,
337
- collapsedLines = 5,
338
- compact = false,
339
- persistentCopy = false,
340
- copyPlacement = "auto",
341
- className,
342
- ...htmlProps
343
- }, ref) {
344
- const [copied, setCopied] = useState(false);
345
- const [highlightedHtml, setHighlightedHtml] = useState("");
346
- const [isLoading, setIsLoading] = useState(true);
347
- const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
348
- const trimmedCode = useMemo(() => normalizeCode(code), [code]);
349
- const codeLines = trimmedCode.split("\n");
350
- const totalLines = codeLines.length;
351
- const shouldShowCollapse = collapsible && totalLines > collapsedLines;
352
- const visibleCode = shouldShowCollapse && isCollapsed ? codeLines.slice(0, collapsedLines).join("\n") : trimmedCode;
353
- const highlightSet = useMemo(() => parseLineSpec(highlightLines), [highlightLines]);
354
- const addedSet = useMemo(() => parseLineSpec(addedLines), [addedLines]);
355
- const removedSet = useMemo(() => parseLineSpec(removedLines), [removedLines]);
356
- const hasDiff = addedSet.size > 0 || removedSet.size > 0;
357
- const resolvedCopyPlacement = copyPlacement === "auto" ? filename ? "header" : "overlay" : copyPlacement;
358
- const shouldShowHeaderCopy = showCopy && !persistentCopy && resolvedCopyPlacement === "header";
359
- const shouldShowOverlayCopy = showCopy && !persistentCopy && resolvedCopyPlacement === "overlay";
360
- const shouldRenderHeader = Boolean(filename) || shouldShowHeaderCopy;
361
- useEffect(() => {
362
- let cancelled = false;
363
- setIsLoading(true);
364
- loadShikiDeps();
365
- if (_shikiFailed || !_codeToHtml) {
366
- if (_shikiFailed && process.env.NODE_ENV === "development") {
367
- console.warn(
368
- "[@fragments-sdk/ui] CodeBlock: shiki is not installed. Install it with: npm install shiki"
369
- );
370
- }
371
- setHighlightedHtml(
372
- `<pre class="shiki"><code>${escapeHtml(visibleCode)}</code></pre>`
315
+ const CodeBlockBase = React.forwardRef(function CodeBlock2({
316
+ code,
317
+ language = "tsx",
318
+ theme = "one-dark-pro",
319
+ showCopy = true,
320
+ title,
321
+ filename,
322
+ caption,
323
+ showLineNumbers = false,
324
+ startLineNumber = 1,
325
+ highlightLines,
326
+ addedLines,
327
+ removedLines,
328
+ wordWrap = false,
329
+ maxHeight,
330
+ collapsible = false,
331
+ defaultCollapsed = false,
332
+ collapsedLines = 5,
333
+ compact = false,
334
+ persistentCopy = false,
335
+ copyPlacement = "auto",
336
+ onCopy,
337
+ className,
338
+ ...htmlProps
339
+ }, ref) {
340
+ const [copied, setCopied] = useState(false);
341
+ const [highlightedHtml, setHighlightedHtml] = useState("");
342
+ const [isLoading, setIsLoading] = useState(true);
343
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
344
+ const trimmedCode = useMemo(() => normalizeCode(code), [code]);
345
+ const codeLines = trimmedCode.split("\n");
346
+ const totalLines = codeLines.length;
347
+ const shouldShowCollapse = collapsible && totalLines > collapsedLines;
348
+ const visibleCode = shouldShowCollapse && isCollapsed ? codeLines.slice(0, collapsedLines).join("\n") : trimmedCode;
349
+ const highlightSet = useMemo(() => parseLineSpec(highlightLines), [highlightLines]);
350
+ const addedSet = useMemo(() => parseLineSpec(addedLines), [addedLines]);
351
+ const removedSet = useMemo(() => parseLineSpec(removedLines), [removedLines]);
352
+ const hasDiff = addedSet.size > 0 || removedSet.size > 0;
353
+ const resolvedCopyPlacement = copyPlacement === "auto" ? filename ? "header" : "overlay" : copyPlacement;
354
+ const shouldShowHeaderCopy = showCopy && !persistentCopy && resolvedCopyPlacement === "header";
355
+ const shouldShowOverlayCopy = showCopy && !persistentCopy && resolvedCopyPlacement === "overlay";
356
+ const shouldRenderHeader = Boolean(filename) || shouldShowHeaderCopy;
357
+ useEffect(() => {
358
+ let cancelled = false;
359
+ setIsLoading(true);
360
+ loadShikiDeps();
361
+ if (_shikiFailed || !_codeToHtml) {
362
+ if (_shikiFailed && process.env.NODE_ENV === "development") {
363
+ console.warn(
364
+ "[@fragments-sdk/ui] CodeBlock: shiki is not installed. Install it with: npm install shiki"
373
365
  );
366
+ }
367
+ setHighlightedHtml(`<pre class="shiki"><code>${escapeHtml(visibleCode)}</code></pre>`);
368
+ setIsLoading(false);
369
+ return;
370
+ }
371
+ _codeToHtml(visibleCode, {
372
+ lang: language,
373
+ theme
374
+ }).then((html) => {
375
+ if (!cancelled) {
376
+ const processed = processShikiHtml(html, {
377
+ showLineNumbers,
378
+ startLineNumber,
379
+ highlightLines: highlightSet,
380
+ addedLines: addedSet,
381
+ removedLines: removedSet
382
+ });
383
+ setHighlightedHtml(processed);
374
384
  setIsLoading(false);
375
- return;
376
385
  }
377
- _codeToHtml(visibleCode, {
378
- lang: language,
379
- theme
380
- }).then((html) => {
381
- if (!cancelled) {
382
- const processed = processShikiHtml(html, {
383
- showLineNumbers,
384
- startLineNumber,
385
- highlightLines: highlightSet,
386
- addedLines: addedSet,
387
- removedLines: removedSet
388
- });
389
- setHighlightedHtml(processed);
390
- setIsLoading(false);
391
- }
392
- }).catch((err) => {
393
- if (process.env.NODE_ENV !== "production") {
394
- console.error("Syntax highlighting failed:", err);
395
- }
396
- if (!cancelled) {
397
- setHighlightedHtml(
398
- `<pre class="shiki"><code>${escapeHtml(visibleCode)}</code></pre>`
399
- );
400
- setIsLoading(false);
401
- }
402
- });
403
- return () => {
404
- cancelled = true;
405
- };
406
- }, [visibleCode, language, theme, showLineNumbers, startLineNumber, highlightSet, addedSet, removedSet]);
407
- const handleCopy = useCallback(async () => {
408
- try {
409
- await navigator.clipboard.writeText(trimmedCode);
410
- setCopied(true);
411
- setTimeout(() => setCopied(false), 2e3);
412
- } catch (err) {
413
- if (process.env.NODE_ENV !== "production") {
414
- console.error("Failed to copy:", err);
415
- }
386
+ }).catch((err) => {
387
+ if (process.env.NODE_ENV !== "production") {
388
+ console.error("Syntax highlighting failed:", err);
389
+ }
390
+ if (!cancelled) {
391
+ setHighlightedHtml(`<pre class="shiki"><code>${escapeHtml(visibleCode)}</code></pre>`);
392
+ setIsLoading(false);
416
393
  }
417
- }, [trimmedCode]);
418
- const toggleCollapsed = useCallback(() => {
419
- setIsCollapsed((prev) => !prev);
420
- }, []);
421
- const classNames = [
422
- styles.container,
423
- showLineNumbers && styles.withLineNumbers,
424
- hasDiff && styles.withDiff,
425
- wordWrap && styles.wordWrap,
426
- compact && styles.compact,
427
- className
428
- ].filter(Boolean).join(" ");
429
- const wrapperClasses = [
430
- styles.wrapper,
431
- persistentCopy && styles.persistentCopyWrapper,
432
- shouldShowOverlayCopy && styles.withCopyOverlay
433
- ].filter(Boolean).join(" ");
434
- const codeContainerStyle = maxHeight ? { maxHeight, overflow: "auto" } : {};
435
- return /* @__PURE__ */ jsxs("div", { ref, ...htmlProps, className: classNames, "data-theme": "dark", children: [
436
- title && /* @__PURE__ */ jsx("div", { className: styles.title, children: title }),
437
- /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
438
- shouldRenderHeader && /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
439
- /* @__PURE__ */ jsx("span", { className: styles.filename, children: filename ?? "" }),
440
- shouldShowHeaderCopy && /* @__PURE__ */ jsx(
441
- "button",
442
- {
443
- type: "button",
444
- onClick: handleCopy,
445
- className: `${styles.copyButton} ${copied ? styles.copied : ""}`,
446
- "aria-label": copied ? "Copied!" : "Copy code",
447
- children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: styles.icon }) : /* @__PURE__ */ jsx(CopyIcon, { className: styles.icon })
448
- }
449
- )
450
- ] }),
451
- shouldShowOverlayCopy && /* @__PURE__ */ jsx(
394
+ });
395
+ return () => {
396
+ cancelled = true;
397
+ };
398
+ }, [
399
+ visibleCode,
400
+ language,
401
+ theme,
402
+ showLineNumbers,
403
+ startLineNumber,
404
+ highlightSet,
405
+ addedSet,
406
+ removedSet
407
+ ]);
408
+ const handleCopy = useCallback(async () => {
409
+ try {
410
+ await navigator.clipboard.writeText(trimmedCode);
411
+ setCopied(true);
412
+ setTimeout(() => setCopied(false), 2e3);
413
+ onCopy == null ? void 0 : onCopy();
414
+ } catch (err) {
415
+ if (process.env.NODE_ENV !== "production") {
416
+ console.error("Failed to copy:", err);
417
+ }
418
+ }
419
+ }, [trimmedCode, onCopy]);
420
+ const toggleCollapsed = useCallback(() => {
421
+ setIsCollapsed((prev) => !prev);
422
+ }, []);
423
+ const classNames = [
424
+ styles.container,
425
+ showLineNumbers && styles.withLineNumbers,
426
+ hasDiff && styles.withDiff,
427
+ wordWrap && styles.wordWrap,
428
+ compact && styles.compact,
429
+ className
430
+ ].filter(Boolean).join(" ");
431
+ const wrapperClasses = [
432
+ styles.wrapper,
433
+ persistentCopy && styles.persistentCopyWrapper,
434
+ shouldShowOverlayCopy && styles.withCopyOverlay
435
+ ].filter(Boolean).join(" ");
436
+ const codeContainerStyle = maxHeight ? { maxHeight, overflow: "auto" } : {};
437
+ return /* @__PURE__ */ jsxs("div", { ref, ...htmlProps, className: classNames, "data-theme": "dark", children: [
438
+ title && /* @__PURE__ */ jsx("div", { className: styles.title, children: title }),
439
+ /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
440
+ shouldRenderHeader && /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
441
+ /* @__PURE__ */ jsx("span", { className: styles.filename, children: filename ?? "" }),
442
+ shouldShowHeaderCopy && /* @__PURE__ */ jsx(
452
443
  "button",
453
444
  {
454
445
  type: "button",
455
446
  onClick: handleCopy,
456
- className: `${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : ""}`,
447
+ className: `${styles.copyButton} ${copied ? styles.copied : ""}`,
457
448
  "aria-label": copied ? "Copied!" : "Copy code",
458
449
  children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: styles.icon }) : /* @__PURE__ */ jsx(CopyIcon, { className: styles.icon })
459
450
  }
460
- ),
461
- isLoading ? /* @__PURE__ */ jsx("div", { className: styles.loading, style: codeContainerStyle, children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: visibleCode }) }) }) : /* @__PURE__ */ jsx(
462
- "div",
463
- {
464
- className: styles.codeContainer,
465
- style: codeContainerStyle,
466
- dangerouslySetInnerHTML: { __html: highlightedHtml }
467
- }
468
- ),
469
- persistentCopy && /* @__PURE__ */ jsx("div", { className: styles.persistentCopy, children: /* @__PURE__ */ jsx(
470
- Button,
471
- {
472
- size: "sm",
473
- onClick: handleCopy,
474
- "aria-label": copied ? "Copied!" : "Copy code",
475
- icon: copied ? true : false,
476
- children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: styles.icon }) : /* @__PURE__ */ jsx(CopyIcon, { className: styles.icon })
477
- }
478
- ) }),
479
- shouldShowCollapse && /* @__PURE__ */ jsx(
480
- "button",
481
- {
482
- type: "button",
483
- onClick: toggleCollapsed,
484
- className: styles.collapseButton,
485
- "aria-expanded": !isCollapsed,
486
- "aria-label": isCollapsed ? "Expand code" : "Collapse code",
487
- children: isCollapsed ? /* @__PURE__ */ jsxs(Fragment, { children: [
488
- /* @__PURE__ */ jsx(ChevronDownIcon, { className: styles.icon }),
489
- /* @__PURE__ */ jsxs("span", { children: [
490
- "Show ",
491
- totalLines - collapsedLines,
492
- " more lines"
493
- ] })
494
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
495
- /* @__PURE__ */ jsx(ChevronUpIcon, { className: styles.icon }),
496
- /* @__PURE__ */ jsx("span", { children: "Show less" })
497
- ] })
498
- }
499
451
  )
500
452
  ] }),
501
- caption && /* @__PURE__ */ jsx("div", { className: styles.caption, children: caption })
502
- ] });
503
- }
504
- );
453
+ shouldShowOverlayCopy && /* @__PURE__ */ jsx(
454
+ "button",
455
+ {
456
+ type: "button",
457
+ onClick: handleCopy,
458
+ className: `${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : ""}`,
459
+ "aria-label": copied ? "Copied!" : "Copy code",
460
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: styles.icon }) : /* @__PURE__ */ jsx(CopyIcon, { className: styles.icon })
461
+ }
462
+ ),
463
+ isLoading ? /* @__PURE__ */ jsx("div", { className: styles.loading, style: codeContainerStyle, children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: visibleCode }) }) }) : /* @__PURE__ */ jsx(
464
+ "div",
465
+ {
466
+ className: styles.codeContainer,
467
+ style: codeContainerStyle,
468
+ dangerouslySetInnerHTML: { __html: highlightedHtml }
469
+ }
470
+ ),
471
+ persistentCopy && /* @__PURE__ */ jsx(
472
+ "button",
473
+ {
474
+ type: "button",
475
+ onClick: handleCopy,
476
+ className: `${styles.persistentCopy} ${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : ""}`,
477
+ "aria-label": copied ? "Copied!" : "Copy code",
478
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: styles.icon }) : /* @__PURE__ */ jsx(CopyIcon, { className: styles.icon })
479
+ }
480
+ ),
481
+ shouldShowCollapse && /* @__PURE__ */ jsx(
482
+ "button",
483
+ {
484
+ type: "button",
485
+ onClick: toggleCollapsed,
486
+ className: styles.collapseButton,
487
+ "aria-expanded": !isCollapsed,
488
+ "aria-label": isCollapsed ? "Expand code" : "Collapse code",
489
+ children: isCollapsed ? /* @__PURE__ */ jsxs(Fragment, { children: [
490
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: styles.icon }),
491
+ /* @__PURE__ */ jsxs("span", { children: [
492
+ "Show ",
493
+ totalLines - collapsedLines,
494
+ " more lines"
495
+ ] })
496
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
497
+ /* @__PURE__ */ jsx(ChevronUpIcon, { className: styles.icon }),
498
+ /* @__PURE__ */ jsx("span", { children: "Show less" })
499
+ ] })
500
+ }
501
+ )
502
+ ] }),
503
+ caption && /* @__PURE__ */ jsx("div", { className: styles.caption, children: caption })
504
+ ] });
505
+ });
505
506
  function TabbedCodeBlock({
506
507
  tabs,
507
508
  defaultTab,
@@ -512,7 +513,8 @@ function TabbedCodeBlock({
512
513
  tabsVariant = "pills",
513
514
  wordWrap,
514
515
  maxHeight,
515
- className
516
+ className,
517
+ onCopy
516
518
  }) {
517
519
  var _a;
518
520
  const defaultValue = defaultTab || ((_a = tabs[0]) == null ? void 0 : _a.label) || "";
@@ -528,7 +530,8 @@ function TabbedCodeBlock({
528
530
  copyPlacement,
529
531
  showLineNumbers,
530
532
  wordWrap,
531
- maxHeight
533
+ maxHeight,
534
+ onCopy: onCopy ? () => onCopy(tab.label) : void 0
532
535
  }
533
536
  ) }, tab.label))
534
537
  ] }) });
@@ -1 +1 @@
1
- {"version":3,"file":"codeblock.js","sources":["../src/components/CodeBlock/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useState, useCallback, useEffect, useMemo } from 'react';\n// ============================================\n// Lazy-loaded dependency (shiki)\n// ============================================\n\nlet _codeToHtml: ((code: string, options: { lang: string; theme: string }) => Promise<string>) | null = null;\nlet _shikiLoaded = false;\nlet _shikiFailed = false;\n\nfunction loadShikiDeps() {\n if (_shikiLoaded) return;\n _shikiLoaded = true;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const shiki = require('shiki');\n _codeToHtml = shiki.codeToHtml;\n } catch {\n _shikiFailed = true;\n }\n}\nimport { TabsRoot, TabsList, Tab, TabsPanel } from '../Tabs';\nimport { Button } from '../Button';\nimport styles from './CodeBlock.module.scss';\nimport '../../styles/globals.scss';\n\nexport type CodeBlockLanguage =\n | 'tsx'\n | 'typescript'\n | 'javascript'\n | 'jsx'\n | 'bash'\n | 'shell'\n | 'css'\n | 'scss'\n | 'sass'\n | 'json'\n | 'html'\n | 'xml'\n | 'markdown'\n | 'md'\n | 'yaml'\n | 'yml'\n | 'python'\n | 'py'\n | 'ruby'\n | 'go'\n | 'rust'\n | 'java'\n | 'kotlin'\n | 'swift'\n | 'c'\n | 'cpp'\n | 'csharp'\n | 'php'\n | 'sql'\n | 'graphql'\n | 'diff'\n | 'plaintext';\n\n/** Available syntax highlighting themes */\nexport type CodeBlockTheme =\n | 'synthwave-84'\n | 'github-dark'\n | 'github-light'\n | 'one-dark-pro'\n | 'dracula'\n | 'nord'\n | 'monokai'\n | 'vitesse-dark'\n | 'vitesse-light'\n | 'min-dark'\n | 'min-light';\n\nexport type CodeBlockCopyPlacement = 'auto' | 'header' | 'overlay';\n\nexport interface CodeBlockProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Code string to display */\n code: string;\n /** Programming language for syntax highlighting */\n language?: CodeBlockLanguage;\n /** Syntax highlighting theme */\n theme?: CodeBlockTheme;\n /** Show copy button */\n showCopy?: boolean;\n /** Optional title above code block (external label) */\n title?: string;\n /** Optional filename shown in header bar inside code block */\n filename?: string;\n /** Optional caption below code block */\n caption?: string;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Starting line number (default: 1) */\n startLineNumber?: number;\n /** Highlight specific lines (e.g., [1, 3, '5-7']) */\n highlightLines?: (number | string)[];\n /** Lines marked as added in diff view */\n addedLines?: (number | string)[];\n /** Lines marked as removed in diff view */\n removedLines?: (number | string)[];\n /** Enable word wrapping for long lines */\n wordWrap?: boolean;\n /** Maximum height in pixels (enables scrolling) */\n maxHeight?: number;\n /** Allow collapsing/expanding the code block */\n collapsible?: boolean;\n /** Initial collapsed state (only applies when collapsible is true) */\n defaultCollapsed?: boolean;\n /** Number of lines to show when collapsed */\n collapsedLines?: number;\n /** Compact mode with reduced padding */\n compact?: boolean;\n /** Show a persistent copy button (always visible, uses Button component) */\n persistentCopy?: boolean;\n /** Placement of copy button when not using persistent copy */\n copyPlacement?: CodeBlockCopyPlacement;\n}\n\nfunction CopyIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction ChevronUpIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n );\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n/**\n * Remove common leading whitespace from all lines (dedent).\n * This handles template literals that have extra indentation from code formatting.\n */\nfunction dedent(str: string): string {\n const lines = str.split('\\n');\n\n // Find the minimum indentation (ignoring empty lines)\n let minIndent = Infinity;\n for (const line of lines) {\n if (line.trim() === '') continue;\n const match = line.match(/^(\\s*)/);\n if (match) {\n minIndent = Math.min(minIndent, match[1].length);\n }\n }\n\n // If no indentation found, return as-is\n if (minIndent === Infinity || minIndent === 0) {\n return str;\n }\n\n // Remove the common indentation from all lines\n return lines\n .map(line => line.slice(minIndent))\n .join('\\n');\n}\n\n/**\n * Normalize indentation while handling JSX where first line is already at column 0.\n */\nfunction normalizeIndentation(str: string): string {\n const lines = str.split('\\n');\n if (lines.length <= 1) return str;\n\n let minIndent = Infinity;\n const firstLineIndent = lines[0].match(/^(\\s*)/)?.[1].length ?? 0;\n\n for (let i = 1; i < lines.length; i += 1) {\n const line = lines[i];\n if (line.trim().length === 0) continue;\n const indent = line.match(/^(\\s*)/)?.[1].length ?? 0;\n minIndent = Math.min(minIndent, indent);\n }\n\n if (firstLineIndent > 0) {\n minIndent = Math.min(minIndent, firstLineIndent);\n }\n\n if (minIndent === Infinity || minIndent === 0) return str;\n\n return lines\n .map((line) => line.slice(Math.min(minIndent, line.match(/^(\\s*)/)?.[1].length ?? 0)))\n .join('\\n');\n}\n\nfunction trimTrailingWhitespace(str: string): string {\n return str\n .split('\\n')\n .map((line) => line.replace(/[ \\t]+$/g, ''))\n .join('\\n');\n}\n\nfunction findTagEnd(line: string): number {\n let quote: '\"' | '\\'' | '`' | null = null;\n let escaped = false;\n let braceDepth = 0;\n let bracketDepth = 0;\n let parenDepth = 0;\n\n for (let i = 1; i < line.length; i += 1) {\n const char = line[i];\n\n if (quote) {\n if (char === '\\\\' && !escaped) {\n escaped = true;\n continue;\n }\n if (char === quote && !escaped) {\n quote = null;\n }\n escaped = false;\n continue;\n }\n\n if (char === '\"' || char === '\\'' || char === '`') {\n quote = char;\n continue;\n }\n\n if (char === '{') braceDepth += 1;\n else if (char === '}') braceDepth = Math.max(0, braceDepth - 1);\n else if (char === '[') bracketDepth += 1;\n else if (char === ']') bracketDepth = Math.max(0, bracketDepth - 1);\n else if (char === '(') parenDepth += 1;\n else if (char === ')') parenDepth = Math.max(0, parenDepth - 1);\n else if (char === '>' && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {\n return i;\n }\n }\n\n return -1;\n}\n\nfunction splitJsxAttributes(attrs: string): string[] {\n const parts: string[] = [];\n let current = '';\n let quote: '\"' | '\\'' | '`' | null = null;\n let escaped = false;\n let braceDepth = 0;\n let bracketDepth = 0;\n let parenDepth = 0;\n\n for (const char of attrs) {\n if (quote) {\n current += char;\n if (char === '\\\\' && !escaped) {\n escaped = true;\n continue;\n }\n if (char === quote && !escaped) {\n quote = null;\n }\n escaped = false;\n continue;\n }\n\n if (char === '\"' || char === '\\'' || char === '`') {\n quote = char;\n current += char;\n continue;\n }\n\n if (char === '{') braceDepth += 1;\n else if (char === '}') braceDepth = Math.max(0, braceDepth - 1);\n else if (char === '[') bracketDepth += 1;\n else if (char === ']') bracketDepth = Math.max(0, bracketDepth - 1);\n else if (char === '(') parenDepth += 1;\n else if (char === ')') parenDepth = Math.max(0, parenDepth - 1);\n\n if (/\\s/.test(char) && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {\n if (current.trim().length > 0) {\n parts.push(current.trim());\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current.trim().length > 0) {\n parts.push(current.trim());\n }\n\n return parts;\n}\n\nfunction formatLongJsxTagLine(line: string): string {\n const maxInlineLength = 110;\n if (line.length <= maxInlineLength) return line;\n\n const indent = line.match(/^(\\s*)/)?.[1] ?? '';\n const trimmed = line.trimStart();\n\n if (\n !trimmed.startsWith('<')\n || trimmed.startsWith('</')\n || trimmed.startsWith('<!')\n || trimmed.startsWith('<?')\n ) {\n return line;\n }\n\n const tagEnd = findTagEnd(trimmed);\n if (tagEnd === -1) return line;\n if (trimmed.slice(tagEnd + 1).trim().length > 0) return line;\n\n const rawTagBody = trimmed.slice(1, tagEnd).trim();\n const isSelfClosing = rawTagBody.endsWith('/');\n const tagBody = isSelfClosing ? rawTagBody.slice(0, -1).trimEnd() : rawTagBody;\n const firstSpace = tagBody.search(/\\s/);\n if (firstSpace === -1) return line;\n\n const tagName = tagBody.slice(0, firstSpace);\n if (!/^[A-Za-z][\\w.:-]*$/.test(tagName)) return line;\n\n const attrsSource = tagBody.slice(firstSpace).trim();\n if (!attrsSource.includes('=') && !attrsSource.includes('{...')) return line;\n\n const attrs = splitJsxAttributes(attrsSource);\n if (attrs.length === 0) return line;\n\n const attrIndent = `${indent} `;\n const close = isSelfClosing ? '/>' : '>';\n\n return [\n `${indent}<${tagName}`,\n ...attrs.map((attr) => `${attrIndent}${attr}`),\n `${indent}${close}`,\n ].join('\\n');\n}\n\nfunction formatLongJsxTags(code: string): string {\n return code\n .split('\\n')\n .flatMap((line) => formatLongJsxTagLine(line).split('\\n'))\n .join('\\n');\n}\n\nfunction normalizeCode(code: string): string {\n const trimmed = code.trim();\n if (trimmed.length === 0) return '';\n\n const normalized = normalizeIndentation(trimmed);\n const dedented = dedent(normalized);\n const withoutTrailingWhitespace = trimTrailingWhitespace(dedented);\n return formatLongJsxTags(withoutTrailingWhitespace);\n}\n\n/**\n * Parse line specification into a Set of line numbers.\n * Supports: [1, 3, '5-7'] -> Set {1, 3, 5, 6, 7}\n */\nfunction parseLineSpec(spec?: (number | string)[]): Set<number> {\n const lines = new Set<number>();\n if (!spec) return lines;\n\n for (const item of spec) {\n if (typeof item === 'number') {\n lines.add(item);\n } else if (typeof item === 'string') {\n const rangeMatch = item.match(/^(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const start = parseInt(rangeMatch[1], 10);\n const end = parseInt(rangeMatch[2], 10);\n for (let i = start; i <= end; i++) {\n lines.add(i);\n }\n } else {\n const num = parseInt(item, 10);\n if (!isNaN(num)) {\n lines.add(num);\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface ProcessOptions {\n showLineNumbers: boolean;\n startLineNumber: number;\n highlightLines: Set<number>;\n addedLines: Set<number>;\n removedLines: Set<number>;\n}\n\n/**\n * Add line numbers, highlight classes, and diff markers to Shiki HTML output.\n */\nfunction processShikiHtml(html: string, options: ProcessOptions): string {\n const { showLineNumbers, startLineNumber, highlightLines, addedLines, removedLines } = options;\n const hasDiff = addedLines.size > 0 || removedLines.size > 0;\n\n if (!showLineNumbers && highlightLines.size === 0 && !hasDiff) {\n return html;\n }\n\n // Extract the code content from Shiki output\n // Shiki outputs: <pre class=\"shiki ...\"><code>...lines...</code></pre>\n const codeMatch = html.match(/<code[^>]*>([\\s\\S]*?)<\\/code>/);\n if (!codeMatch) return html;\n\n const codeContent = codeMatch[1];\n const lines = codeContent.split('\\n');\n\n // Process each line\n const processedLines = lines.map((line, index) => {\n const lineNum = index + 1;\n const displayLineNum = startLineNumber + index;\n const isHighlighted = highlightLines.has(lineNum);\n const isAdded = addedLines.has(lineNum);\n const isRemoved = removedLines.has(lineNum);\n\n const lineClasses = ['line'];\n if (isHighlighted) lineClasses.push('highlighted');\n if (isAdded) lineClasses.push('diff-added');\n if (isRemoved) lineClasses.push('diff-removed');\n\n const lineClass = lineClasses.join(' ');\n const diffMarker = isAdded ? '+' : isRemoved ? '-' : ' ';\n\n if (showLineNumbers || hasDiff) {\n const lineNumHtml = showLineNumbers\n ? `<span class=\"line-number\">${displayLineNum}</span>`\n : '';\n const diffMarkerHtml = hasDiff\n ? `<span class=\"diff-marker\">${diffMarker}</span>`\n : '';\n return `<span class=\"${lineClass}\">${lineNumHtml}${diffMarkerHtml}${line}</span>`;\n }\n return `<span class=\"${lineClass}\">${line}</span>`;\n });\n\n // Reconstruct the HTML\n return html.replace(\n /<code[^>]*>[\\s\\S]*?<\\/code>/,\n `<code>${processedLines.join('\\n')}</code>`\n );\n}\n\nconst CodeBlockBase = React.forwardRef<HTMLDivElement, CodeBlockProps>(\n function CodeBlock(\n {\n code,\n language = 'tsx',\n theme = 'one-dark-pro',\n showCopy = true,\n title,\n filename,\n caption,\n showLineNumbers = false,\n startLineNumber = 1,\n highlightLines,\n addedLines,\n removedLines,\n wordWrap = false,\n maxHeight,\n collapsible = false,\n defaultCollapsed = false,\n collapsedLines = 5,\n compact = false,\n persistentCopy = false,\n copyPlacement = 'auto',\n className,\n ...htmlProps\n },\n ref\n ) {\n const [copied, setCopied] = useState(false);\n const [highlightedHtml, setHighlightedHtml] = useState<string>('');\n const [isLoading, setIsLoading] = useState(true);\n const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);\n\n const trimmedCode = useMemo(() => normalizeCode(code), [code]);\n const codeLines = trimmedCode.split('\\n');\n const totalLines = codeLines.length;\n const shouldShowCollapse = collapsible && totalLines > collapsedLines;\n\n // Compute visible code when collapsed\n const visibleCode = shouldShowCollapse && isCollapsed\n ? codeLines.slice(0, collapsedLines).join('\\n')\n : trimmedCode;\n\n const highlightSet = useMemo(() => parseLineSpec(highlightLines), [highlightLines]);\n const addedSet = useMemo(() => parseLineSpec(addedLines), [addedLines]);\n const removedSet = useMemo(() => parseLineSpec(removedLines), [removedLines]);\n const hasDiff = addedSet.size > 0 || removedSet.size > 0;\n const resolvedCopyPlacement = copyPlacement === 'auto'\n ? (filename ? 'header' : 'overlay')\n : copyPlacement;\n const shouldShowHeaderCopy = showCopy && !persistentCopy && resolvedCopyPlacement === 'header';\n const shouldShowOverlayCopy = showCopy && !persistentCopy && resolvedCopyPlacement === 'overlay';\n const shouldRenderHeader = Boolean(filename) || shouldShowHeaderCopy;\n\n // Apply syntax highlighting\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n\n loadShikiDeps();\n\n if (_shikiFailed || !_codeToHtml) {\n if (_shikiFailed && process.env.NODE_ENV === 'development') {\n console.warn(\n '[@fragments-sdk/ui] CodeBlock: shiki is not installed. ' +\n 'Install it with: npm install shiki'\n );\n }\n // Fallback to plain text without syntax highlighting\n setHighlightedHtml(\n `<pre class=\"shiki\"><code>${escapeHtml(visibleCode)}</code></pre>`\n );\n setIsLoading(false);\n return;\n }\n\n _codeToHtml(visibleCode, {\n lang: language,\n theme,\n })\n .then((html) => {\n if (!cancelled) {\n const processed = processShikiHtml(html, {\n showLineNumbers,\n startLineNumber,\n highlightLines: highlightSet,\n addedLines: addedSet,\n removedLines: removedSet,\n });\n setHighlightedHtml(processed);\n setIsLoading(false);\n }\n })\n .catch((err) => {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Syntax highlighting failed:', err);\n }\n if (!cancelled) {\n // Fallback to plain text\n setHighlightedHtml(\n `<pre class=\"shiki\"><code>${escapeHtml(visibleCode)}</code></pre>`\n );\n setIsLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [visibleCode, language, theme, showLineNumbers, startLineNumber, highlightSet, addedSet, removedSet]);\n\n const handleCopy = useCallback(async () => {\n try {\n // Always copy the full code, even when collapsed\n await navigator.clipboard.writeText(trimmedCode);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Failed to copy:', err);\n }\n }\n }, [trimmedCode]);\n\n const toggleCollapsed = useCallback(() => {\n setIsCollapsed((prev) => !prev);\n }, []);\n\n const classNames = [\n styles.container,\n showLineNumbers && styles.withLineNumbers,\n hasDiff && styles.withDiff,\n wordWrap && styles.wordWrap,\n compact && styles.compact,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const wrapperClasses = [\n styles.wrapper,\n persistentCopy && styles.persistentCopyWrapper,\n shouldShowOverlayCopy && styles.withCopyOverlay,\n ].filter(Boolean).join(' ');\n\n const codeContainerStyle: React.CSSProperties = maxHeight\n ? { maxHeight, overflow: 'auto' }\n : {};\n\n return (\n <div ref={ref} {...htmlProps} className={classNames} data-theme=\"dark\">\n {title && <div className={styles.title}>{title}</div>}\n <div className={wrapperClasses}>\n {shouldRenderHeader && (\n <div className={styles.header}>\n <span className={styles.filename}>{filename ?? ''}</span>\n {shouldShowHeaderCopy && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`${styles.copyButton} ${copied ? styles.copied : ''}`}\n aria-label={copied ? 'Copied!' : 'Copy code'}\n >\n {copied ? <CheckIcon className={styles.icon} /> : <CopyIcon className={styles.icon} />}\n </button>\n )}\n </div>\n )}\n {shouldShowOverlayCopy && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : ''}`}\n aria-label={copied ? 'Copied!' : 'Copy code'}\n >\n {copied ? <CheckIcon className={styles.icon} /> : <CopyIcon className={styles.icon} />}\n </button>\n )}\n {isLoading ? (\n <div className={styles.loading} style={codeContainerStyle}>\n <pre>\n <code>{visibleCode}</code>\n </pre>\n </div>\n ) : (\n <div\n className={styles.codeContainer}\n style={codeContainerStyle}\n dangerouslySetInnerHTML={{ __html: highlightedHtml }}\n />\n )}\n {persistentCopy && (\n <div className={styles.persistentCopy}>\n <Button\n size=\"sm\"\n onClick={handleCopy}\n aria-label={copied ? 'Copied!' : 'Copy code'}\n icon={copied ? true : false}\n >\n {copied ? <CheckIcon className={styles.icon} /> : <CopyIcon className={styles.icon} />}\n </Button>\n </div>\n )}\n {shouldShowCollapse && (\n <button\n type=\"button\"\n onClick={toggleCollapsed}\n className={styles.collapseButton}\n aria-expanded={!isCollapsed}\n aria-label={isCollapsed ? 'Expand code' : 'Collapse code'}\n >\n {isCollapsed ? (\n <>\n <ChevronDownIcon className={styles.icon} />\n <span>Show {totalLines - collapsedLines} more lines</span>\n </>\n ) : (\n <>\n <ChevronUpIcon className={styles.icon} />\n <span>Show less</span>\n </>\n )}\n </button>\n )}\n </div>\n {caption && <div className={styles.caption}>{caption}</div>}\n </div>\n );\n }\n);\n\n// ============================================\n// Tabbed Code Block\n// ============================================\n\nexport interface CodeBlockTab {\n /** Label shown in the tab */\n label: string;\n /** Code string to display */\n code: string;\n /** Programming language for syntax highlighting */\n language?: CodeBlockLanguage;\n}\n\nexport interface TabbedCodeBlockProps {\n /** Array of code tabs */\n tabs: CodeBlockTab[];\n /** Default selected tab (by label) */\n defaultTab?: string;\n /** Show copy button */\n showCopy?: boolean;\n /** Placement of copy button when not using persistent copy */\n copyPlacement?: CodeBlockCopyPlacement;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Syntax highlighting theme (applies to all tabs) */\n theme?: CodeBlockTheme;\n /** Tab list visual style */\n tabsVariant?: 'underline' | 'pills';\n /** Enable word wrapping for long lines */\n wordWrap?: boolean;\n /** Maximum height in pixels (enables scrolling) */\n maxHeight?: number;\n /** Additional class name */\n className?: string;\n}\n\nfunction TabbedCodeBlock({\n tabs,\n defaultTab,\n showCopy = true,\n copyPlacement = 'auto',\n showLineNumbers = false,\n theme,\n tabsVariant = 'pills',\n wordWrap,\n maxHeight,\n className,\n}: TabbedCodeBlockProps) {\n const defaultValue = defaultTab || tabs[0]?.label || '';\n\n return (\n <div className={className}>\n <TabsRoot defaultValue={defaultValue}>\n <TabsList variant={tabsVariant}>\n {tabs.map((tab) => (\n <Tab key={tab.label} value={tab.label}>\n {tab.label}\n </Tab>\n ))}\n </TabsList>\n {tabs.map((tab) => (\n <TabsPanel key={tab.label} value={tab.label} flush className={styles.tabbedPanel}>\n <CodeBlockBase\n code={tab.code}\n language={tab.language}\n theme={theme}\n showCopy={showCopy}\n copyPlacement={copyPlacement}\n showLineNumbers={showLineNumbers}\n wordWrap={wordWrap}\n maxHeight={maxHeight}\n />\n </TabsPanel>\n ))}\n </TabsRoot>\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const CodeBlock = Object.assign(CodeBlockBase, {\n Tabbed: TabbedCodeBlock,\n});\n\nexport { TabbedCodeBlock };\n"],"names":["_a","CodeBlock"],"mappings":"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"}
1
+ {"version":3,"file":"codeblock.js","sources":["../src/components/CodeBlock/index.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { useState, useCallback, useEffect, useMemo } from \"react\";\n// ============================================\n// Lazy-loaded dependency (shiki)\n// ============================================\n\nlet _codeToHtml:\n | ((code: string, options: { lang: string; theme: string }) => Promise<string>)\n | null = null;\nlet _shikiLoaded = false;\nlet _shikiFailed = false;\n\nfunction loadShikiDeps() {\n if (_shikiLoaded) return;\n _shikiLoaded = true;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const shiki = require(\"shiki\");\n _codeToHtml = shiki.codeToHtml;\n } catch {\n _shikiFailed = true;\n }\n}\nimport { TabsRoot, TabsList, Tab, TabsPanel } from \"../Tabs\";\nimport { Button } from \"../Button\";\nimport styles from \"./CodeBlock.module.scss\";\nimport \"../../styles/globals.scss\";\n\nexport type CodeBlockLanguage =\n | \"tsx\"\n | \"typescript\"\n | \"javascript\"\n | \"jsx\"\n | \"bash\"\n | \"shell\"\n | \"css\"\n | \"scss\"\n | \"sass\"\n | \"json\"\n | \"html\"\n | \"xml\"\n | \"markdown\"\n | \"md\"\n | \"yaml\"\n | \"yml\"\n | \"python\"\n | \"py\"\n | \"ruby\"\n | \"go\"\n | \"rust\"\n | \"java\"\n | \"kotlin\"\n | \"swift\"\n | \"c\"\n | \"cpp\"\n | \"csharp\"\n | \"php\"\n | \"sql\"\n | \"graphql\"\n | \"diff\"\n | \"plaintext\";\n\n/** Available syntax highlighting themes */\nexport type CodeBlockTheme =\n | \"synthwave-84\"\n | \"github-dark\"\n | \"github-light\"\n | \"one-dark-pro\"\n | \"dracula\"\n | \"nord\"\n | \"monokai\"\n | \"vitesse-dark\"\n | \"vitesse-light\"\n | \"min-dark\"\n | \"min-light\";\n\nexport type CodeBlockCopyPlacement = \"auto\" | \"header\" | \"overlay\";\n\nexport interface CodeBlockProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Code string to display */\n code: string;\n /** Programming language for syntax highlighting */\n language?: CodeBlockLanguage;\n /** Syntax highlighting theme */\n theme?: CodeBlockTheme;\n /** Show copy button */\n showCopy?: boolean;\n /** Optional title above code block (external label) */\n title?: string;\n /** Optional filename shown in header bar inside code block */\n filename?: string;\n /** Optional caption below code block */\n caption?: string;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Starting line number (default: 1) */\n startLineNumber?: number;\n /** Highlight specific lines (e.g., [1, 3, '5-7']) */\n highlightLines?: (number | string)[];\n /** Lines marked as added in diff view */\n addedLines?: (number | string)[];\n /** Lines marked as removed in diff view */\n removedLines?: (number | string)[];\n /** Enable word wrapping for long lines */\n wordWrap?: boolean;\n /** Maximum height in pixels (enables scrolling) */\n maxHeight?: number;\n /** Allow collapsing/expanding the code block */\n collapsible?: boolean;\n /** Initial collapsed state (only applies when collapsible is true) */\n defaultCollapsed?: boolean;\n /** Number of lines to show when collapsed */\n collapsedLines?: number;\n /** Compact mode with reduced padding */\n compact?: boolean;\n /** Show a persistent copy button (always visible, uses Button component) */\n persistentCopy?: boolean;\n /** Placement of copy button when not using persistent copy */\n copyPlacement?: CodeBlockCopyPlacement;\n /** Callback fired when the copy button is clicked and copy succeeds */\n onCopy?: () => void;\n}\n\nfunction CopyIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction ChevronUpIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n );\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n}\n\n/**\n * Remove common leading whitespace from all lines (dedent).\n * This handles template literals that have extra indentation from code formatting.\n */\nfunction dedent(str: string): string {\n const lines = str.split(\"\\n\");\n\n // Find the minimum indentation (ignoring empty lines)\n let minIndent = Infinity;\n for (const line of lines) {\n if (line.trim() === \"\") continue;\n const match = line.match(/^(\\s*)/);\n if (match) {\n minIndent = Math.min(minIndent, match[1].length);\n }\n }\n\n // If no indentation found, return as-is\n if (minIndent === Infinity || minIndent === 0) {\n return str;\n }\n\n // Remove the common indentation from all lines\n return lines.map((line) => line.slice(minIndent)).join(\"\\n\");\n}\n\n/**\n * Normalize indentation while handling JSX where first line is already at column 0.\n */\nfunction normalizeIndentation(str: string): string {\n const lines = str.split(\"\\n\");\n if (lines.length <= 1) return str;\n\n let minIndent = Infinity;\n const firstLineIndent = lines[0].match(/^(\\s*)/)?.[1].length ?? 0;\n\n for (let i = 1; i < lines.length; i += 1) {\n const line = lines[i];\n if (line.trim().length === 0) continue;\n const indent = line.match(/^(\\s*)/)?.[1].length ?? 0;\n minIndent = Math.min(minIndent, indent);\n }\n\n if (firstLineIndent > 0) {\n minIndent = Math.min(minIndent, firstLineIndent);\n }\n\n if (minIndent === Infinity || minIndent === 0) return str;\n\n return lines\n .map((line) => line.slice(Math.min(minIndent, line.match(/^(\\s*)/)?.[1].length ?? 0)))\n .join(\"\\n\");\n}\n\nfunction trimTrailingWhitespace(str: string): string {\n return str\n .split(\"\\n\")\n .map((line) => line.replace(/[ \\t]+$/g, \"\"))\n .join(\"\\n\");\n}\n\nfunction findTagEnd(line: string): number {\n let quote: '\"' | \"'\" | \"`\" | null = null;\n let escaped = false;\n let braceDepth = 0;\n let bracketDepth = 0;\n let parenDepth = 0;\n\n for (let i = 1; i < line.length; i += 1) {\n const char = line[i];\n\n if (quote) {\n if (char === \"\\\\\" && !escaped) {\n escaped = true;\n continue;\n }\n if (char === quote && !escaped) {\n quote = null;\n }\n escaped = false;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n continue;\n }\n\n if (char === \"{\") braceDepth += 1;\n else if (char === \"}\") braceDepth = Math.max(0, braceDepth - 1);\n else if (char === \"[\") bracketDepth += 1;\n else if (char === \"]\") bracketDepth = Math.max(0, bracketDepth - 1);\n else if (char === \"(\") parenDepth += 1;\n else if (char === \")\") parenDepth = Math.max(0, parenDepth - 1);\n else if (char === \">\" && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {\n return i;\n }\n }\n\n return -1;\n}\n\nfunction splitJsxAttributes(attrs: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let quote: '\"' | \"'\" | \"`\" | null = null;\n let escaped = false;\n let braceDepth = 0;\n let bracketDepth = 0;\n let parenDepth = 0;\n\n for (const char of attrs) {\n if (quote) {\n current += char;\n if (char === \"\\\\\" && !escaped) {\n escaped = true;\n continue;\n }\n if (char === quote && !escaped) {\n quote = null;\n }\n escaped = false;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n current += char;\n continue;\n }\n\n if (char === \"{\") braceDepth += 1;\n else if (char === \"}\") braceDepth = Math.max(0, braceDepth - 1);\n else if (char === \"[\") bracketDepth += 1;\n else if (char === \"]\") bracketDepth = Math.max(0, bracketDepth - 1);\n else if (char === \"(\") parenDepth += 1;\n else if (char === \")\") parenDepth = Math.max(0, parenDepth - 1);\n\n if (/\\s/.test(char) && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {\n if (current.trim().length > 0) {\n parts.push(current.trim());\n current = \"\";\n }\n continue;\n }\n\n current += char;\n }\n\n if (current.trim().length > 0) {\n parts.push(current.trim());\n }\n\n return parts;\n}\n\nfunction formatLongJsxTagLine(line: string): string {\n const maxInlineLength = 110;\n if (line.length <= maxInlineLength) return line;\n\n const indent = line.match(/^(\\s*)/)?.[1] ?? \"\";\n const trimmed = line.trimStart();\n\n if (\n !trimmed.startsWith(\"<\") ||\n trimmed.startsWith(\"</\") ||\n trimmed.startsWith(\"<!\") ||\n trimmed.startsWith(\"<?\")\n ) {\n return line;\n }\n\n const tagEnd = findTagEnd(trimmed);\n if (tagEnd === -1) return line;\n if (trimmed.slice(tagEnd + 1).trim().length > 0) return line;\n\n const rawTagBody = trimmed.slice(1, tagEnd).trim();\n const isSelfClosing = rawTagBody.endsWith(\"/\");\n const tagBody = isSelfClosing ? rawTagBody.slice(0, -1).trimEnd() : rawTagBody;\n const firstSpace = tagBody.search(/\\s/);\n if (firstSpace === -1) return line;\n\n const tagName = tagBody.slice(0, firstSpace);\n if (!/^[A-Za-z][\\w.:-]*$/.test(tagName)) return line;\n\n const attrsSource = tagBody.slice(firstSpace).trim();\n if (!attrsSource.includes(\"=\") && !attrsSource.includes(\"{...\")) return line;\n\n const attrs = splitJsxAttributes(attrsSource);\n if (attrs.length === 0) return line;\n\n const attrIndent = `${indent} `;\n const close = isSelfClosing ? \"/>\" : \">\";\n\n return [\n `${indent}<${tagName}`,\n ...attrs.map((attr) => `${attrIndent}${attr}`),\n `${indent}${close}`,\n ].join(\"\\n\");\n}\n\nfunction formatLongJsxTags(code: string): string {\n return code\n .split(\"\\n\")\n .flatMap((line) => formatLongJsxTagLine(line).split(\"\\n\"))\n .join(\"\\n\");\n}\n\nfunction normalizeCode(code: string): string {\n const trimmed = code.trim();\n if (trimmed.length === 0) return \"\";\n\n const normalized = normalizeIndentation(trimmed);\n const dedented = dedent(normalized);\n const withoutTrailingWhitespace = trimTrailingWhitespace(dedented);\n return formatLongJsxTags(withoutTrailingWhitespace);\n}\n\n/**\n * Parse line specification into a Set of line numbers.\n * Supports: [1, 3, '5-7'] -> Set {1, 3, 5, 6, 7}\n */\nfunction parseLineSpec(spec?: (number | string)[]): Set<number> {\n const lines = new Set<number>();\n if (!spec) return lines;\n\n for (const item of spec) {\n if (typeof item === \"number\") {\n lines.add(item);\n } else if (typeof item === \"string\") {\n const rangeMatch = item.match(/^(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const start = parseInt(rangeMatch[1], 10);\n const end = parseInt(rangeMatch[2], 10);\n for (let i = start; i <= end; i++) {\n lines.add(i);\n }\n } else {\n const num = parseInt(item, 10);\n if (!isNaN(num)) {\n lines.add(num);\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface ProcessOptions {\n showLineNumbers: boolean;\n startLineNumber: number;\n highlightLines: Set<number>;\n addedLines: Set<number>;\n removedLines: Set<number>;\n}\n\n/**\n * Add line numbers, highlight classes, and diff markers to Shiki HTML output.\n */\nfunction processShikiHtml(html: string, options: ProcessOptions): string {\n const { showLineNumbers, startLineNumber, highlightLines, addedLines, removedLines } = options;\n const hasDiff = addedLines.size > 0 || removedLines.size > 0;\n\n if (!showLineNumbers && highlightLines.size === 0 && !hasDiff) {\n return html;\n }\n\n // Extract the code content from Shiki output\n // Shiki outputs: <pre class=\"shiki ...\"><code>...lines...</code></pre>\n const codeMatch = html.match(/<code[^>]*>([\\s\\S]*?)<\\/code>/);\n if (!codeMatch) return html;\n\n const codeContent = codeMatch[1];\n const lines = codeContent.split(\"\\n\");\n\n // Process each line\n const processedLines = lines.map((line, index) => {\n const lineNum = index + 1;\n const displayLineNum = startLineNumber + index;\n const isHighlighted = highlightLines.has(lineNum);\n const isAdded = addedLines.has(lineNum);\n const isRemoved = removedLines.has(lineNum);\n\n const lineClasses = [\"line\"];\n if (isHighlighted) lineClasses.push(\"highlighted\");\n if (isAdded) lineClasses.push(\"diff-added\");\n if (isRemoved) lineClasses.push(\"diff-removed\");\n\n const lineClass = lineClasses.join(\" \");\n const diffMarker = isAdded ? \"+\" : isRemoved ? \"-\" : \" \";\n\n if (showLineNumbers || hasDiff) {\n const lineNumHtml = showLineNumbers\n ? `<span class=\"line-number\">${displayLineNum}</span>`\n : \"\";\n const diffMarkerHtml = hasDiff ? `<span class=\"diff-marker\">${diffMarker}</span>` : \"\";\n return `<span class=\"${lineClass}\">${lineNumHtml}${diffMarkerHtml}${line}</span>`;\n }\n return `<span class=\"${lineClass}\">${line}</span>`;\n });\n\n // Reconstruct the HTML\n return html.replace(/<code[^>]*>[\\s\\S]*?<\\/code>/, `<code>${processedLines.join(\"\\n\")}</code>`);\n}\n\nconst CodeBlockBase = React.forwardRef<HTMLDivElement, CodeBlockProps>(function CodeBlock(\n {\n code,\n language = \"tsx\",\n theme = \"one-dark-pro\",\n showCopy = true,\n title,\n filename,\n caption,\n showLineNumbers = false,\n startLineNumber = 1,\n highlightLines,\n addedLines,\n removedLines,\n wordWrap = false,\n maxHeight,\n collapsible = false,\n defaultCollapsed = false,\n collapsedLines = 5,\n compact = false,\n persistentCopy = false,\n copyPlacement = \"auto\",\n onCopy,\n className,\n ...htmlProps\n },\n ref\n) {\n const [copied, setCopied] = useState(false);\n const [highlightedHtml, setHighlightedHtml] = useState<string>(\"\");\n const [isLoading, setIsLoading] = useState(true);\n const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);\n\n const trimmedCode = useMemo(() => normalizeCode(code), [code]);\n const codeLines = trimmedCode.split(\"\\n\");\n const totalLines = codeLines.length;\n const shouldShowCollapse = collapsible && totalLines > collapsedLines;\n\n // Compute visible code when collapsed\n const visibleCode =\n shouldShowCollapse && isCollapsed ? codeLines.slice(0, collapsedLines).join(\"\\n\") : trimmedCode;\n\n const highlightSet = useMemo(() => parseLineSpec(highlightLines), [highlightLines]);\n const addedSet = useMemo(() => parseLineSpec(addedLines), [addedLines]);\n const removedSet = useMemo(() => parseLineSpec(removedLines), [removedLines]);\n const hasDiff = addedSet.size > 0 || removedSet.size > 0;\n const resolvedCopyPlacement =\n copyPlacement === \"auto\" ? (filename ? \"header\" : \"overlay\") : copyPlacement;\n const shouldShowHeaderCopy = showCopy && !persistentCopy && resolvedCopyPlacement === \"header\";\n const shouldShowOverlayCopy = showCopy && !persistentCopy && resolvedCopyPlacement === \"overlay\";\n const shouldRenderHeader = Boolean(filename) || shouldShowHeaderCopy;\n\n // Apply syntax highlighting\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n\n loadShikiDeps();\n\n if (_shikiFailed || !_codeToHtml) {\n if (_shikiFailed && process.env.NODE_ENV === \"development\") {\n console.warn(\n \"[@fragments-sdk/ui] CodeBlock: shiki is not installed. \" +\n \"Install it with: npm install shiki\"\n );\n }\n // Fallback to plain text without syntax highlighting\n setHighlightedHtml(`<pre class=\"shiki\"><code>${escapeHtml(visibleCode)}</code></pre>`);\n setIsLoading(false);\n return;\n }\n\n _codeToHtml(visibleCode, {\n lang: language,\n theme,\n })\n .then((html) => {\n if (!cancelled) {\n const processed = processShikiHtml(html, {\n showLineNumbers,\n startLineNumber,\n highlightLines: highlightSet,\n addedLines: addedSet,\n removedLines: removedSet,\n });\n setHighlightedHtml(processed);\n setIsLoading(false);\n }\n })\n .catch((err) => {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"Syntax highlighting failed:\", err);\n }\n if (!cancelled) {\n // Fallback to plain text\n setHighlightedHtml(`<pre class=\"shiki\"><code>${escapeHtml(visibleCode)}</code></pre>`);\n setIsLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n visibleCode,\n language,\n theme,\n showLineNumbers,\n startLineNumber,\n highlightSet,\n addedSet,\n removedSet,\n ]);\n\n const handleCopy = useCallback(async () => {\n try {\n // Always copy the full code, even when collapsed\n await navigator.clipboard.writeText(trimmedCode);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n onCopy?.();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"Failed to copy:\", err);\n }\n }\n }, [trimmedCode, onCopy]);\n\n const toggleCollapsed = useCallback(() => {\n setIsCollapsed((prev) => !prev);\n }, []);\n\n const classNames = [\n styles.container,\n showLineNumbers && styles.withLineNumbers,\n hasDiff && styles.withDiff,\n wordWrap && styles.wordWrap,\n compact && styles.compact,\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const wrapperClasses = [\n styles.wrapper,\n persistentCopy && styles.persistentCopyWrapper,\n shouldShowOverlayCopy && styles.withCopyOverlay,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const codeContainerStyle: React.CSSProperties = maxHeight ? { maxHeight, overflow: \"auto\" } : {};\n\n return (\n <div ref={ref} {...htmlProps} className={classNames} data-theme=\"dark\">\n {title && <div className={styles.title}>{title}</div>}\n <div className={wrapperClasses}>\n {shouldRenderHeader && (\n <div className={styles.header}>\n <span className={styles.filename}>{filename ?? \"\"}</span>\n {shouldShowHeaderCopy && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`${styles.copyButton} ${copied ? styles.copied : \"\"}`}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n {copied ? (\n <CheckIcon className={styles.icon} />\n ) : (\n <CopyIcon className={styles.icon} />\n )}\n </button>\n )}\n </div>\n )}\n {shouldShowOverlayCopy && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : \"\"}`}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n {copied ? <CheckIcon className={styles.icon} /> : <CopyIcon className={styles.icon} />}\n </button>\n )}\n {isLoading ? (\n <div className={styles.loading} style={codeContainerStyle}>\n <pre>\n <code>{visibleCode}</code>\n </pre>\n </div>\n ) : (\n <div\n className={styles.codeContainer}\n style={codeContainerStyle}\n dangerouslySetInnerHTML={{ __html: highlightedHtml }}\n />\n )}\n {persistentCopy && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`${styles.persistentCopy} ${styles.copyButton} ${styles.copyOverlay} ${copied ? styles.copied : \"\"}`}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n {copied ? <CheckIcon className={styles.icon} /> : <CopyIcon className={styles.icon} />}\n </button>\n )}\n {shouldShowCollapse && (\n <button\n type=\"button\"\n onClick={toggleCollapsed}\n className={styles.collapseButton}\n aria-expanded={!isCollapsed}\n aria-label={isCollapsed ? \"Expand code\" : \"Collapse code\"}\n >\n {isCollapsed ? (\n <>\n <ChevronDownIcon className={styles.icon} />\n <span>Show {totalLines - collapsedLines} more lines</span>\n </>\n ) : (\n <>\n <ChevronUpIcon className={styles.icon} />\n <span>Show less</span>\n </>\n )}\n </button>\n )}\n </div>\n {caption && <div className={styles.caption}>{caption}</div>}\n </div>\n );\n});\n\n// ============================================\n// Tabbed Code Block\n// ============================================\n\nexport interface CodeBlockTab {\n /** Label shown in the tab */\n label: string;\n /** Code string to display */\n code: string;\n /** Programming language for syntax highlighting */\n language?: CodeBlockLanguage;\n}\n\nexport interface TabbedCodeBlockProps {\n /** Array of code tabs */\n tabs: CodeBlockTab[];\n /** Default selected tab (by label) */\n defaultTab?: string;\n /** Show copy button */\n showCopy?: boolean;\n /** Placement of copy button when not using persistent copy */\n copyPlacement?: CodeBlockCopyPlacement;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Syntax highlighting theme (applies to all tabs) */\n theme?: CodeBlockTheme;\n /** Tab list visual style */\n tabsVariant?: \"underline\" | \"pills\";\n /** Enable word wrapping for long lines */\n wordWrap?: boolean;\n /** Maximum height in pixels (enables scrolling) */\n maxHeight?: number;\n /** Additional class name */\n className?: string;\n /** Callback fired when a tab's copy button is clicked. Receives the tab label. */\n onCopy?: (tabLabel: string) => void;\n}\n\nfunction TabbedCodeBlock({\n tabs,\n defaultTab,\n showCopy = true,\n copyPlacement = \"auto\",\n showLineNumbers = false,\n theme,\n tabsVariant = \"pills\",\n wordWrap,\n maxHeight,\n className,\n onCopy,\n}: TabbedCodeBlockProps) {\n const defaultValue = defaultTab || tabs[0]?.label || \"\";\n\n return (\n <div className={className}>\n <TabsRoot defaultValue={defaultValue}>\n <TabsList variant={tabsVariant}>\n {tabs.map((tab) => (\n <Tab key={tab.label} value={tab.label}>\n {tab.label}\n </Tab>\n ))}\n </TabsList>\n {tabs.map((tab) => (\n <TabsPanel key={tab.label} value={tab.label} flush className={styles.tabbedPanel}>\n <CodeBlockBase\n code={tab.code}\n language={tab.language}\n theme={theme}\n showCopy={showCopy}\n copyPlacement={copyPlacement}\n showLineNumbers={showLineNumbers}\n wordWrap={wordWrap}\n maxHeight={maxHeight}\n onCopy={onCopy ? () => onCopy(tab.label) : undefined}\n />\n </TabsPanel>\n ))}\n </TabsRoot>\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const CodeBlock = Object.assign(CodeBlockBase, {\n Tabbed: TabbedCodeBlock,\n});\n\nexport { TabbedCodeBlock };\n"],"names":["_a","CodeBlock"],"mappings":"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"}