@djangocfg/ui-tools 2.1.355 → 2.1.357

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 (70) hide show
  1. package/dist/ChatRoot-6U7633X3.mjs +5 -0
  2. package/dist/{ChatRoot-2KT32NFJ.cjs.map → ChatRoot-6U7633X3.mjs.map} +1 -1
  3. package/dist/ChatRoot-HARTIAJ5.cjs +14 -0
  4. package/dist/{ChatRoot-VSIBJLE2.mjs.map → ChatRoot-HARTIAJ5.cjs.map} +1 -1
  5. package/dist/{DocsLayout-VFPPNKSQ.mjs → DocsLayout-HGYIJTF3.mjs} +4 -4
  6. package/dist/{DocsLayout-VFPPNKSQ.mjs.map → DocsLayout-HGYIJTF3.mjs.map} +1 -1
  7. package/dist/{DocsLayout-N5ZJZPBY.cjs → DocsLayout-OQHDNKZE.cjs} +11 -11
  8. package/dist/{DocsLayout-N5ZJZPBY.cjs.map → DocsLayout-OQHDNKZE.cjs.map} +1 -1
  9. package/dist/JsonTree-43PQAJKY.mjs +5 -0
  10. package/dist/{JsonTree-55625VVH.mjs.map → JsonTree-43PQAJKY.mjs.map} +1 -1
  11. package/dist/JsonTree-X6W5YEVY.cjs +11 -0
  12. package/dist/{JsonTree-DCM5QGWF.cjs.map → JsonTree-X6W5YEVY.cjs.map} +1 -1
  13. package/dist/TreeRoot-5COOOSWG.mjs +4 -0
  14. package/dist/{TreeRoot-N72OYKXU.cjs.map → TreeRoot-5COOOSWG.mjs.map} +1 -1
  15. package/dist/TreeRoot-AABP2J6Y.cjs +19 -0
  16. package/dist/{TreeRoot-VGAIXCUA.mjs.map → TreeRoot-AABP2J6Y.cjs.map} +1 -1
  17. package/dist/{chunk-5G5YBFS6.mjs → chunk-ECONRHIG.mjs} +7 -7
  18. package/dist/chunk-ECONRHIG.mjs.map +1 -0
  19. package/dist/{chunk-IEEAENLX.cjs → chunk-FVVF7VCD.cjs} +14 -10
  20. package/dist/chunk-FVVF7VCD.cjs.map +1 -0
  21. package/dist/{chunk-2ZLKZ5VR.mjs → chunk-NWUT327A.mjs} +110 -32
  22. package/dist/chunk-NWUT327A.mjs.map +1 -0
  23. package/dist/{chunk-2SXDCXLK.cjs → chunk-OPKFKTIN.cjs} +17 -15
  24. package/dist/chunk-OPKFKTIN.cjs.map +1 -0
  25. package/dist/{chunk-SGP7V2UW.cjs → chunk-T3MWM23F.cjs} +6 -6
  26. package/dist/chunk-T3MWM23F.cjs.map +1 -0
  27. package/dist/{chunk-XJ7CXHSU.mjs → chunk-WGU5BEZX.mjs} +16 -14
  28. package/dist/chunk-WGU5BEZX.mjs.map +1 -0
  29. package/dist/{chunk-B5AWZOHJ.cjs → chunk-XACCHZH2.cjs} +119 -41
  30. package/dist/chunk-XACCHZH2.cjs.map +1 -0
  31. package/dist/{chunk-G5IEC7SR.mjs → chunk-ZL7FH4NW.mjs} +15 -11
  32. package/dist/chunk-ZL7FH4NW.mjs.map +1 -0
  33. package/dist/index.cjs +93 -93
  34. package/dist/index.d.cts +39 -4
  35. package/dist/index.d.ts +39 -4
  36. package/dist/index.mjs +10 -10
  37. package/dist/tree/index.cjs +33 -33
  38. package/dist/tree/index.d.cts +34 -4
  39. package/dist/tree/index.d.ts +34 -4
  40. package/dist/tree/index.mjs +1 -1
  41. package/package.json +6 -6
  42. package/src/components/markdown/MarkdownMessage/ActionRow.tsx +8 -3
  43. package/src/components/markdown/MarkdownMessage/ChatMessageRow.tsx +10 -4
  44. package/src/components/markdown/MarkdownMessage/CodeBlock.tsx +18 -6
  45. package/src/components/markdown/MarkdownMessage/CollapseToggle.tsx +13 -6
  46. package/src/components/markdown/MarkdownMessage/MarkdownMessage.tsx +10 -3
  47. package/src/tools/Chat/components/ChatRoot.tsx +12 -4
  48. package/src/tools/Chat/components/MessageActions.tsx +13 -3
  49. package/src/tools/Chat/components/StreamingIndicator.tsx +11 -1
  50. package/src/tools/JsonTree/components/JsonContent.tsx +13 -4
  51. package/src/tools/JsonTree/components/JsonToolbar.tsx +10 -3
  52. package/src/tools/JsonTree/index.tsx +10 -3
  53. package/src/tools/Tree/components/TreeChevron.tsx +10 -1
  54. package/src/tools/Tree/components/TreeIcon.tsx +11 -1
  55. package/src/tools/Tree/components/TreeLabel.tsx +10 -1
  56. package/src/tools/Tree/components/TreeRow.tsx +11 -1
  57. package/dist/ChatRoot-2KT32NFJ.cjs +0 -14
  58. package/dist/ChatRoot-VSIBJLE2.mjs +0 -5
  59. package/dist/JsonTree-55625VVH.mjs +0 -5
  60. package/dist/JsonTree-DCM5QGWF.cjs +0 -11
  61. package/dist/TreeRoot-N72OYKXU.cjs +0 -19
  62. package/dist/TreeRoot-VGAIXCUA.mjs +0 -4
  63. package/dist/chunk-2SXDCXLK.cjs.map +0 -1
  64. package/dist/chunk-2ZLKZ5VR.mjs.map +0 -1
  65. package/dist/chunk-5G5YBFS6.mjs.map +0 -1
  66. package/dist/chunk-B5AWZOHJ.cjs.map +0 -1
  67. package/dist/chunk-G5IEC7SR.mjs.map +0 -1
  68. package/dist/chunk-IEEAENLX.cjs.map +0 -1
  69. package/dist/chunk-SGP7V2UW.cjs.map +0 -1
  70. package/dist/chunk-XJ7CXHSU.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkOLISEQHS_cjs = require('./chunk-OLISEQHS.cjs');
4
- var React6 = require('react');
4
+ var React8 = require('react');
5
5
  require('@djangocfg/ui-core/styles/palette');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var ReactMarkdown = require('react-markdown');
@@ -17,7 +17,7 @@ var hooks = require('@djangocfg/ui-core/hooks');
17
17
 
18
18
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
19
19
 
20
- var React6__default = /*#__PURE__*/_interopDefault(React6);
20
+ var React8__default = /*#__PURE__*/_interopDefault(React8);
21
21
  var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
22
22
  var rehypeExternalLinks__default = /*#__PURE__*/_interopDefault(rehypeExternalLinks);
23
23
  var rehypeRaw__default = /*#__PURE__*/_interopDefault(rehypeRaw);
@@ -100,10 +100,10 @@ function fixUnclosedMarkdown(content) {
100
100
  chunkOLISEQHS_cjs.__name(fixUnclosedMarkdown, "fixUnclosedMarkdown");
101
101
  function useCollapsibleContent(content, options = {}) {
102
102
  const { maxLength, maxLines, defaultExpanded = false } = options;
103
- const [isCollapsed, setIsCollapsed] = React6.useState(!defaultExpanded);
103
+ const [isCollapsed, setIsCollapsed] = React8.useState(!defaultExpanded);
104
104
  const originalLength = content.length;
105
105
  const originalLineCount = content.split("\n").length;
106
- const { shouldCollapse, truncatedContent } = React6.useMemo(() => {
106
+ const { shouldCollapse, truncatedContent } = React8.useMemo(() => {
107
107
  if (maxLength === void 0 && maxLines === void 0) {
108
108
  return { shouldCollapse: false, truncatedContent: content };
109
109
  }
@@ -119,16 +119,16 @@ function useCollapsibleContent(content, options = {}) {
119
119
  }
120
120
  return { shouldCollapse: needsCollapse, truncatedContent: result };
121
121
  }, [content, maxLength, maxLines, originalLineCount]);
122
- const displayContent = React6.useMemo(() => {
122
+ const displayContent = React8.useMemo(() => {
123
123
  if (!shouldCollapse || !isCollapsed) {
124
124
  return content;
125
125
  }
126
126
  return truncatedContent;
127
127
  }, [content, truncatedContent, shouldCollapse, isCollapsed]);
128
- const toggleCollapsed = React6.useCallback(() => {
128
+ const toggleCollapsed = React8.useCallback(() => {
129
129
  setIsCollapsed((prev) => !prev);
130
130
  }, []);
131
- const setCollapsed = React6.useCallback((collapsed) => {
131
+ const setCollapsed = React8.useCallback((collapsed) => {
132
132
  setIsCollapsed(collapsed);
133
133
  }, []);
134
134
  return {
@@ -145,7 +145,7 @@ chunkOLISEQHS_cjs.__name(useCollapsibleContent, "useCollapsibleContent");
145
145
  function extractTextFromChildren(children) {
146
146
  if (typeof children === "string") return children;
147
147
  if (typeof children === "number") return String(children);
148
- if (React6__default.default.isValidElement(children)) {
148
+ if (React8__default.default.isValidElement(children)) {
149
149
  const props = children.props;
150
150
  return extractTextFromChildren(props.children);
151
151
  }
@@ -204,19 +204,19 @@ function hasMarkdownSyntax(text) {
204
204
  return patterns.some((p) => p.test(text));
205
205
  }
206
206
  chunkOLISEQHS_cjs.__name(hasMarkdownSyntax, "hasMarkdownSyntax");
207
- var MermaidClient = React6.lazy(() => import('./Mermaid.client-NNTI6DFX.cjs'));
207
+ var MermaidClient = React8.lazy(() => import('./Mermaid.client-NNTI6DFX.cjs'));
208
208
  var LoadingFallback = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center items-center min-h-[100px]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-6 w-6 border-b-2 border-primary" }) }), "LoadingFallback");
209
209
  var Mermaid = /* @__PURE__ */ chunkOLISEQHS_cjs.__name((props) => {
210
- return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback, {}), children: /* @__PURE__ */ jsxRuntime.jsx(MermaidClient, { ...props }) });
210
+ return /* @__PURE__ */ jsxRuntime.jsx(React8.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback, {}), children: /* @__PURE__ */ jsxRuntime.jsx(MermaidClient, { ...props }) });
211
211
  }, "Mermaid");
212
212
  var Mermaid_default = Mermaid;
213
- var PrettyCodeClient = React6.lazy(() => import('./PrettyCode.client-KOHDVPPN.cjs'));
213
+ var PrettyCodeClient = React8.lazy(() => import('./PrettyCode.client-KOHDVPPN.cjs'));
214
214
  var LoadingFallback2 = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
215
215
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20" }),
216
216
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Loading code..." })
217
217
  ] }) }) }), "LoadingFallback");
218
218
  var PrettyCode = /* @__PURE__ */ chunkOLISEQHS_cjs.__name((props) => {
219
- return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback2, {}), children: /* @__PURE__ */ jsxRuntime.jsx(PrettyCodeClient, { ...props }) });
219
+ return /* @__PURE__ */ jsxRuntime.jsx(React8.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback2, {}), children: /* @__PURE__ */ jsxRuntime.jsx(PrettyCodeClient, { ...props }) });
220
220
  }, "PrettyCode");
221
221
  var PrettyCode_default = PrettyCode;
222
222
  var HTML_SCHEMA_BASE = {
@@ -267,7 +267,7 @@ function buildUrlTransform(extraProtocols) {
267
267
  };
268
268
  }
269
269
  chunkOLISEQHS_cjs.__name(buildUrlTransform, "buildUrlTransform");
270
- var CodeBlock = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({ code, language }) => {
270
+ function CodeBlockRaw({ code, language }) {
271
271
  const theme = hooks.useResolvedTheme();
272
272
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-2", children: /* @__PURE__ */ jsxRuntime.jsx(
273
273
  PrettyCode_default,
@@ -281,8 +281,10 @@ var CodeBlock = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({ code, language }) =>
281
281
  scrollIsolation: false
282
282
  }
283
283
  ) });
284
- }, "CodeBlock");
285
- var CodeBlockFallback = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({ code, isUser }) => {
284
+ }
285
+ chunkOLISEQHS_cjs.__name(CodeBlockRaw, "CodeBlockRaw");
286
+ var CodeBlock = React8.memo(CodeBlockRaw);
287
+ function CodeBlockFallbackRaw({ code, isUser }) {
286
288
  const copyHoverClass = isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground";
287
289
  const copyButtonClass = `absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8 ${copyHoverClass}`;
288
290
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group my-3", children: [
@@ -297,7 +299,9 @@ var CodeBlockFallback = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({ code, isUser
297
299
  ),
298
300
  /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-3 rounded text-xs font-mono overflow-x-auto bg-code text-code-foreground border border-code-border", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: code }) })
299
301
  ] });
300
- }, "CodeBlockFallback");
302
+ }
303
+ chunkOLISEQHS_cjs.__name(CodeBlockFallbackRaw, "CodeBlockFallbackRaw");
304
+ var CodeBlockFallback = React8.memo(CodeBlockFallbackRaw);
301
305
  function createMarkdownComponents(isUser = false, isCompact = false) {
302
306
  const textSize = isCompact ? "text-xs" : "text-sm";
303
307
  const headingBase = isCompact ? "text-sm" : "text-base";
@@ -331,7 +335,7 @@ function createMarkdownComponents(isUser = false, isCompact = false) {
331
335
  pre: /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({ children }) => {
332
336
  let codeContent = "";
333
337
  let language = "plaintext";
334
- if (React6__default.default.isValidElement(children)) {
338
+ if (React8__default.default.isValidElement(children)) {
335
339
  const child = children;
336
340
  if (child.type === "code" || typeof child.type === "function" && child.type.name === "code") {
337
341
  const codeProps = child.props;
@@ -403,14 +407,14 @@ function createMarkdownComponents(isUser = false, isCompact = false) {
403
407
  };
404
408
  }
405
409
  chunkOLISEQHS_cjs.__name(createMarkdownComponents, "createMarkdownComponents");
406
- var CollapseToggle = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
410
+ function CollapseToggleRaw({
407
411
  isCollapsed,
408
412
  onClick,
409
413
  readMoreLabel,
410
414
  showLessLabel,
411
415
  isUser,
412
416
  isCompact
413
- }) => {
417
+ }) {
414
418
  const textSize = isCompact ? "text-xs" : "text-sm";
415
419
  return /* @__PURE__ */ jsxRuntime.jsx(
416
420
  "button",
@@ -433,8 +437,9 @@ var CollapseToggle = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
433
437
  ] })
434
438
  }
435
439
  );
436
- }, "CollapseToggle");
437
- function Chevron({ direction }) {
440
+ }
441
+ chunkOLISEQHS_cjs.__name(CollapseToggleRaw, "CollapseToggleRaw");
442
+ var Chevron = React8.memo(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(function Chevron2({ direction }) {
438
443
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
439
444
  "path",
440
445
  {
@@ -444,8 +449,8 @@ function Chevron({ direction }) {
444
449
  d: direction === "down" ? "M19 9l-7 7-7-7" : "M5 15l7-7 7 7"
445
450
  }
446
451
  ) });
447
- }
448
- chunkOLISEQHS_cjs.__name(Chevron, "Chevron");
452
+ }, "Chevron"));
453
+ var CollapseToggle = React8.memo(CollapseToggleRaw);
449
454
  function applyPreprocess(source, rules) {
450
455
  if (!rules || rules.length === 0) return source;
451
456
  let s = source;
@@ -480,8 +485,8 @@ function buildLinkRulesComponent(rules, isUser, callerA) {
480
485
  if (typeof href === "string") {
481
486
  for (const rule of rules) {
482
487
  if (rule.match(href)) {
483
- return React6__default.default.createElement(
484
- React6__default.default.Fragment,
488
+ return React8__default.default.createElement(
489
+ React8__default.default.Fragment,
485
490
  null,
486
491
  rule.render({ href, children, isUser })
487
492
  );
@@ -490,14 +495,14 @@ function buildLinkRulesComponent(rules, isUser, callerA) {
490
495
  }
491
496
  if (callerA && typeof callerA === "function") {
492
497
  const Caller = callerA;
493
- return React6__default.default.createElement(Caller, props);
498
+ return React8__default.default.createElement(Caller, props);
494
499
  }
495
- return React6__default.default.createElement("a", props, children);
500
+ return React8__default.default.createElement("a", props, children);
496
501
  }, "Renderer");
497
502
  return Renderer;
498
503
  }
499
504
  chunkOLISEQHS_cjs.__name(buildLinkRulesComponent, "buildLinkRulesComponent");
500
- var MarkdownMessage = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
505
+ function MarkdownMessageRaw({
501
506
  content,
502
507
  className = "",
503
508
  isUser = false,
@@ -513,23 +518,23 @@ var MarkdownMessage = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
513
518
  showLessLabel = "Show less",
514
519
  defaultExpanded = false,
515
520
  onCollapseChange
516
- }) => {
517
- const preprocessed = React6__default.default.useMemo(
521
+ }) {
522
+ const preprocessed = React8__default.default.useMemo(
518
523
  () => applyPreprocess(content, linkRules),
519
524
  [content, linkRules]
520
525
  );
521
- const effectiveProtocols = React6__default.default.useMemo(
526
+ const effectiveProtocols = React8__default.default.useMemo(
522
527
  () => collectProtocols(extraHrefProtocols, linkRules),
523
528
  [extraHrefProtocols, linkRules]
524
529
  );
525
- const effectiveCustomComponents = React6__default.default.useMemo(() => {
530
+ const effectiveCustomComponents = React8__default.default.useMemo(() => {
526
531
  if (!linkRules || linkRules.length === 0) return customComponents;
527
532
  const callerA = customComponents?.a;
528
533
  const aRenderer = buildLinkRulesComponent(linkRules, isUser, callerA);
529
534
  return { ...customComponents ?? {}, a: aRenderer };
530
535
  }, [customComponents, linkRules, isUser]);
531
536
  const trimmedContent = preprocessed.trim();
532
- const collapsibleOptions = React6__default.default.useMemo(() => {
537
+ const collapsibleOptions = React8__default.default.useMemo(() => {
533
538
  if (!collapsible) return {};
534
539
  return {
535
540
  maxLength: maxLength ?? 1e3,
@@ -538,23 +543,23 @@ var MarkdownMessage = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
538
543
  };
539
544
  }, [collapsible, maxLength, maxLines, defaultExpanded]);
540
545
  const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } = useCollapsibleContent(trimmedContent, collapsible ? collapsibleOptions : {});
541
- React6__default.default.useEffect(() => {
546
+ React8__default.default.useEffect(() => {
542
547
  if (collapsible && shouldCollapse && onCollapseChange) {
543
548
  onCollapseChange(isCollapsed);
544
549
  }
545
550
  }, [isCollapsed, collapsible, shouldCollapse, onCollapseChange]);
546
- const components = React6__default.default.useMemo(() => {
551
+ const components = React8__default.default.useMemo(() => {
547
552
  const base = createMarkdownComponents(isUser, isCompact);
548
553
  return effectiveCustomComponents ? { ...base, ...effectiveCustomComponents } : base;
549
554
  }, [isUser, isCompact, effectiveCustomComponents]);
550
- const schema = React6__default.default.useMemo(() => buildSchema(effectiveProtocols), [effectiveProtocols]);
551
- const urlTransform = React6__default.default.useMemo(
555
+ const schema = React8__default.default.useMemo(() => buildSchema(effectiveProtocols), [effectiveProtocols]);
556
+ const urlTransform = React8__default.default.useMemo(
552
557
  () => buildUrlTransform(effectiveProtocols),
553
558
  [effectiveProtocols]
554
559
  );
555
560
  const textSizeClass = isCompact ? "text-xs" : "text-sm";
556
561
  const proseClass = isCompact ? "prose-xs" : "prose-sm";
557
- const customComponentsBeyondLinks = React6__default.default.useMemo(() => {
562
+ const customComponentsBeyondLinks = React8__default.default.useMemo(() => {
558
563
  if (!customComponents) return false;
559
564
  return Object.keys(customComponents).some((k) => k !== "a");
560
565
  }, [customComponents]);
@@ -638,12 +643,85 @@ var MarkdownMessage = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
638
643
  }
639
644
  )
640
645
  ] });
641
- }, "MarkdownMessage");
646
+ }
647
+ chunkOLISEQHS_cjs.__name(MarkdownMessageRaw, "MarkdownMessageRaw");
648
+ var MarkdownMessage = React8.memo(MarkdownMessageRaw);
649
+ function ActionRowRaw({ value, isUser, visible }) {
650
+ return /* @__PURE__ */ jsxRuntime.jsx(
651
+ "div",
652
+ {
653
+ className: `flex ${isUser ? "justify-end" : "justify-start"}
654
+ transition-opacity duration-150
655
+ ${visible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
656
+ children: /* @__PURE__ */ jsxRuntime.jsx(
657
+ components.CopyButton,
658
+ {
659
+ value,
660
+ size: "icon",
661
+ variant: "ghost",
662
+ iconClassName: "h-3.5 w-3.5",
663
+ className: "h-7 w-7 text-muted-foreground hover:text-foreground",
664
+ tabIndex: visible ? 0 : -1,
665
+ "aria-hidden": !visible
666
+ }
667
+ )
668
+ }
669
+ );
670
+ }
671
+ chunkOLISEQHS_cjs.__name(ActionRowRaw, "ActionRowRaw");
672
+ React8.memo(ActionRowRaw);
673
+ function ChatMessageRowRaw({
674
+ isUser,
675
+ children,
676
+ actions,
677
+ closeDelayMs = 250,
678
+ className = ""
679
+ }) {
680
+ const isTouch = hooks.useMediaQuery("(hover: none), (pointer: coarse)");
681
+ const [hovered, setHovered] = React8.useState(false);
682
+ const closeTimer = React8.useRef(null);
683
+ const cancelClose = React8.useCallback(() => {
684
+ if (closeTimer.current) {
685
+ clearTimeout(closeTimer.current);
686
+ closeTimer.current = null;
687
+ }
688
+ }, []);
689
+ const open = React8.useCallback(() => {
690
+ cancelClose();
691
+ setHovered(true);
692
+ }, [cancelClose]);
693
+ const scheduleClose = React8.useCallback(() => {
694
+ cancelClose();
695
+ closeTimer.current = setTimeout(() => setHovered(false), closeDelayMs);
696
+ }, [cancelClose, closeDelayMs]);
697
+ React8.useEffect(() => () => cancelClose(), [cancelClose]);
698
+ const visible = isTouch || hovered;
699
+ const rowPositionClass = isTouch ? "static mt-1" : "absolute top-full";
700
+ const rowSideClass = isUser ? "right-0" : "left-0";
701
+ return /* @__PURE__ */ jsxRuntime.jsxs(
702
+ "div",
703
+ {
704
+ className: `relative flex flex-col ${isUser ? "items-end" : "items-start"} ${className}`,
705
+ onPointerEnter: isTouch ? void 0 : open,
706
+ onPointerLeave: isTouch ? void 0 : scheduleClose,
707
+ onFocusCapture: open,
708
+ onBlurCapture: (e) => {
709
+ if (!e.currentTarget.contains(e.relatedTarget)) scheduleClose();
710
+ },
711
+ children: [
712
+ children,
713
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${rowPositionClass} ${rowSideClass}`, children: actions(visible, isUser) })
714
+ ]
715
+ }
716
+ );
717
+ }
718
+ chunkOLISEQHS_cjs.__name(ChatMessageRowRaw, "ChatMessageRowRaw");
719
+ React8.memo(ChatMessageRowRaw);
642
720
 
643
721
  exports.MarkdownMessage = MarkdownMessage;
644
722
  exports.Mermaid_default = Mermaid_default;
645
723
  exports.PrettyCode_default = PrettyCode_default;
646
724
  exports.extractTextFromChildren = extractTextFromChildren;
647
725
  exports.useCollapsibleContent = useCollapsibleContent;
648
- //# sourceMappingURL=chunk-B5AWZOHJ.cjs.map
649
- //# sourceMappingURL=chunk-B5AWZOHJ.cjs.map
726
+ //# sourceMappingURL=chunk-XACCHZH2.cjs.map
727
+ //# sourceMappingURL=chunk-XACCHZH2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/markdown/useCollapsibleContent.ts","../src/components/markdown/MarkdownMessage/plainText.ts","../src/tools/Mermaid/index.tsx","../src/tools/PrettyCode/index.tsx","../src/components/markdown/MarkdownMessage/sanitize.ts","../src/components/markdown/MarkdownMessage/CodeBlock.tsx","../src/components/markdown/MarkdownMessage/components.tsx","../src/components/markdown/MarkdownMessage/CollapseToggle.tsx","../src/components/markdown/MarkdownMessage/linkRules.ts","../src/components/markdown/MarkdownMessage/MarkdownMessage.tsx","../src/components/markdown/MarkdownMessage/ActionRow.tsx","../src/components/markdown/MarkdownMessage/ChatMessageRow.tsx"],"names":["__name","useState","useMemo","useCallback","React","lazy","jsx","Suspense","LoadingFallback","jsxs","defaultSchema","useResolvedTheme","memo","CopyButton","Fragment","Chevron","ReactMarkdown","remarkGfm","remarkBreaks","remarkSmartypants","remarkEmoji","rehypeRaw","rehypeSanitize","rehypeExternalLinks","useMediaQuery","useRef","useEffect"],"mappings":"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","file":"chunk-XACCHZH2.cjs","sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\n\nexport interface UseCollapsibleContentOptions {\n /**\n * Maximum character length before collapsing\n * If both maxLength and maxLines are set, the stricter limit applies\n */\n maxLength?: number;\n /**\n * Maximum number of lines before collapsing\n * If both maxLength and maxLines are set, the stricter limit applies\n */\n maxLines?: number;\n /**\n * Start in expanded state (default: false - starts collapsed)\n */\n defaultExpanded?: boolean;\n}\n\nexport interface UseCollapsibleContentResult {\n /** Whether content is currently collapsed */\n isCollapsed: boolean;\n /** Toggle between collapsed/expanded state */\n toggleCollapsed: () => void;\n /** Set collapsed state directly */\n setCollapsed: (collapsed: boolean) => void;\n /** Content to display (truncated if collapsed, full if expanded) */\n displayContent: string;\n /** Whether the content exceeds limits and should be collapsible */\n shouldCollapse: boolean;\n /** Original content length */\n originalLength: number;\n /** Original line count */\n originalLineCount: number;\n}\n\n/**\n * Smart truncation that doesn't break words or markdown syntax\n */\nfunction smartTruncate(content: string, maxLength: number): string {\n if (content.length <= maxLength) {\n return content;\n }\n\n // Find a good break point (space, newline) near maxLength\n let breakPoint = maxLength;\n\n // Look backwards for a space or newline\n while (breakPoint > maxLength - 50 && breakPoint > 0) {\n const char = content[breakPoint];\n if (char === ' ' || char === '\\n' || char === '\\t') {\n break;\n }\n breakPoint--;\n }\n\n // If we couldn't find a good break point, just use maxLength\n if (breakPoint <= maxLength - 50) {\n breakPoint = maxLength;\n }\n\n let truncated = content.slice(0, breakPoint).trimEnd();\n\n // Fix unclosed markdown syntax\n truncated = fixUnclosedMarkdown(truncated);\n\n return truncated;\n}\n\n/**\n * Truncate by line count\n */\nfunction truncateByLines(content: string, maxLines: number): string {\n const lines = content.split('\\n');\n\n if (lines.length <= maxLines) {\n return content;\n }\n\n let truncated = lines.slice(0, maxLines).join('\\n').trimEnd();\n\n // Fix unclosed markdown syntax\n truncated = fixUnclosedMarkdown(truncated);\n\n return truncated;\n}\n\n/**\n * Fix unclosed markdown syntax to prevent rendering issues\n */\nfunction fixUnclosedMarkdown(content: string): string {\n let result = content;\n\n // Count occurrences of markdown markers\n const countOccurrences = (str: string, marker: string): number => {\n const escaped = marker.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const matches = str.match(new RegExp(escaped, 'g'));\n return matches ? matches.length : 0;\n };\n\n // Fix unclosed bold (**) - must have even count\n const boldCount = countOccurrences(result, '**');\n if (boldCount % 2 !== 0) {\n result += '**';\n }\n\n // Fix unclosed italic (*) - but not **\n // Remove ** first for counting, then count single *\n const withoutBold = result.replace(/\\*\\*/g, '');\n const italicCount = countOccurrences(withoutBold, '*');\n if (italicCount % 2 !== 0) {\n result += '*';\n }\n\n // Fix unclosed inline code (`)\n const codeCount = countOccurrences(result, '`');\n // Ignore triple backticks for code blocks\n const tripleCount = countOccurrences(result, '```');\n const singleCodeCount = codeCount - (tripleCount * 3);\n if (singleCodeCount % 2 !== 0) {\n result += '`';\n }\n\n // Fix unclosed code blocks (```)\n if (tripleCount % 2 !== 0) {\n result += '\\n```';\n }\n\n // Fix unclosed strikethrough (~~)\n const strikeCount = countOccurrences(result, '~~');\n if (strikeCount % 2 !== 0) {\n result += '~~';\n }\n\n // Fix unclosed underline bold (__)\n const underlineBoldCount = countOccurrences(result, '__');\n if (underlineBoldCount % 2 !== 0) {\n result += '__';\n }\n\n // Fix unclosed underline italic (_) - but not __\n const withoutUnderlineBold = result.replace(/__/g, '');\n const underlineItalicCount = countOccurrences(withoutUnderlineBold, '_');\n if (underlineItalicCount % 2 !== 0) {\n result += '_';\n }\n\n return result;\n}\n\n/**\n * Hook for managing collapsible content with \"Read more...\" functionality\n *\n * @example\n * ```tsx\n * const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } = useCollapsibleContent(\n * longText,\n * { maxLength: 300, maxLines: 5 }\n * );\n *\n * return (\n * <div>\n * <Markdown content={displayContent} />\n * {shouldCollapse && (\n * <button onClick={toggleCollapsed}>\n * {isCollapsed ? 'Read more...' : 'Show less'}\n * </button>\n * )}\n * </div>\n * );\n * ```\n */\nexport function useCollapsibleContent(\n content: string,\n options: UseCollapsibleContentOptions = {}\n): UseCollapsibleContentResult {\n const { maxLength, maxLines, defaultExpanded = false } = options;\n\n const [isCollapsed, setIsCollapsed] = useState(!defaultExpanded);\n\n const originalLength = content.length;\n const originalLineCount = content.split('\\n').length;\n\n const { shouldCollapse, truncatedContent } = useMemo(() => {\n // If no limits set, don't collapse\n if (maxLength === undefined && maxLines === undefined) {\n return { shouldCollapse: false, truncatedContent: content };\n }\n\n let needsCollapse = false;\n let result = content;\n\n // Check line limit first (usually more restrictive for chat)\n if (maxLines !== undefined && originalLineCount > maxLines) {\n needsCollapse = true;\n result = truncateByLines(result, maxLines);\n }\n\n // Then check character limit\n if (maxLength !== undefined && result.length > maxLength) {\n needsCollapse = true;\n result = smartTruncate(result, maxLength);\n }\n\n return { shouldCollapse: needsCollapse, truncatedContent: result };\n }, [content, maxLength, maxLines, originalLineCount]);\n\n const displayContent = useMemo(() => {\n if (!shouldCollapse || !isCollapsed) {\n return content;\n }\n return truncatedContent;\n }, [content, truncatedContent, shouldCollapse, isCollapsed]);\n\n const toggleCollapsed = useCallback(() => {\n setIsCollapsed((prev) => !prev);\n }, []);\n\n const setCollapsed = useCallback((collapsed: boolean) => {\n setIsCollapsed(collapsed);\n }, []);\n\n return {\n isCollapsed,\n toggleCollapsed,\n setCollapsed,\n displayContent,\n shouldCollapse,\n originalLength,\n originalLineCount,\n };\n}\n\nexport default useCollapsibleContent;\n","import React from 'react';\n\n/** Recursively concatenate the text content of a React.ReactNode tree.\n * Used by the markdown renderers (e.g. `<pre>` extracting code) and\n * by consumers that need a plain-string label out of link children. */\nexport function extractTextFromChildren(children: React.ReactNode): string {\n if (typeof children === 'string') return children;\n if (typeof children === 'number') return String(children);\n if (React.isValidElement(children)) {\n const props = children.props as { children?: React.ReactNode };\n return extractTextFromChildren(props.children);\n }\n if (Array.isArray(children)) {\n return children.map(extractTextFromChildren).join('');\n }\n return '';\n}\n\n/**\n * Auto-detect whether `text` should bypass ReactMarkdown and render as\n * a flat `<div whitespace-pre-wrap>`. Used as the *fallback* when the\n * caller doesn't pass `plainText` explicitly to `MarkdownMessage`.\n *\n * The signal we trust: short, single-paragraph, no markdown markers.\n * Anything longer / multi-paragraph / structurally suggestive falls\n * through to the markdown pipeline — false negatives there are cheap\n * (markdown renders prose correctly), false positives in the prose\n * branch surface as escaped `*` / `#` / etc. so we err markdown-ward.\n *\n * Thresholds were picked from chat-bubble UX research (see ChatGPT,\n * Claude.ai, WhatsApp): roughly \"would a person have written this in\n * one keystroke without thinking about formatting?\". If you find them\n * too tight or too loose, tune here — every consumer goes through\n * `MarkdownMessage` so the change is universal.\n */\nexport function looksLikePlainProse(text: string): boolean {\n const trimmed = text.trim();\n // Empty / whitespace-only — render as plain (cheap path, nothing to parse).\n if (trimmed.length === 0) return true;\n // Long enough that it's likely a structured assistant reply.\n if (trimmed.length > 500) return false;\n // Paragraph break → almost certainly markdown territory.\n if (/\\n\\s*\\n/.test(trimmed)) return false;\n // Many single-line breaks → probably a list or stanza.\n const newlineCount = (trimmed.match(/\\n/g) || []).length;\n if (newlineCount > 4) return false;\n // Any markdown marker → defer to ReactMarkdown.\n if (hasMarkdownSyntax(trimmed)) return false;\n return true;\n}\n\n/** Affordance test: does this string look like markdown? Used to skip\n * the (heavier) ReactMarkdown pipeline when the content is pure\n * prose. NOT a validator — false negatives are fine; false positives\n * cost a render but render correctly. */\nexport function hasMarkdownSyntax(text: string): boolean {\n // Newlines after trim → render as markdown so paragraphs work.\n if (text.trim().includes('\\n')) return true;\n\n // Inline HTML tags (`<br>`, `<b>`, `<code>`, …) — common in OpenAPI\n // descriptions. Without this branch the fast path would escape them\n // and the user sees literal angle brackets.\n if (/<\\/?[a-zA-Z][a-zA-Z0-9-]*(\\s[^>]*)?\\/?>/.test(text)) return true;\n\n const patterns = [\n /^#{1,6}\\s/m, // Headers\n /\\*\\*[^*]+\\*\\*/, // Bold\n /\\*[^*]+\\*/, // Italic\n /__[^_]+__/, // Bold (underscore)\n /_[^_]+_/, // Italic (underscore)\n /\\[.+\\]\\(.+\\)/, // Links\n /!\\[.*\\]\\(.+\\)/, // Images\n /```[\\s\\S]*```/, // Code blocks\n /`[^`]+`/, // Inline code\n /^\\s*[-*+]\\s/m, // Unordered lists\n /^\\s*\\d+\\.\\s/m, // Ordered lists\n /^\\s*>/m, // Blockquotes\n /\\|.+\\|/, // Tables\n /^---+$/m, // Horizontal rules\n /~~[^~]+~~/, // Strikethrough\n ];\n return patterns.some((p) => p.test(text));\n}\n","/**\n * Mermaid Component - Dynamic Import Wrapper\n *\n * Lazy loads the heavy Mermaid library (~800KB) only when needed.\n * This significantly reduces the initial bundle size.\n */\n\n'use client';\n\nimport React, { lazy, Suspense } from 'react';\n\n// Lazy load the client component\nconst MermaidClient = lazy(() => import('./Mermaid.client'));\n\n// Loading fallback component\nconst LoadingFallback = () => (\n <div className=\"flex justify-center items-center min-h-[100px]\">\n <div className=\"animate-spin rounded-full h-6 w-6 border-b-2 border-primary\" />\n </div>\n);\n\nexport interface MermaidProps {\n chart: string;\n className?: string;\n isCompact?: boolean;\n /** Enable click-to-fullscreen functionality (default: true) */\n fullscreen?: boolean;\n /**\n * Enable the FloatingToolbar's \"click to scroll\" lock overlay.\n * Defaults to `false` — Mermaid diagrams don't scroll internally,\n * so the lock overlay just steals page wheel events. See the\n * Mermaid.client implementation for the full rationale.\n */\n scrollIsolation?: boolean;\n}\n\nconst Mermaid: React.FC<MermaidProps> = (props) => {\n return (\n <Suspense fallback={<LoadingFallback />}>\n <MermaidClient {...props} />\n </Suspense>\n );\n};\n\nexport default Mermaid;\n\n// Re-export builders for declarative diagram construction\nexport {\n // Core\n DiagramStore,\n sanitizeLabel,\n toNodeId,\n // Theme hooks\n useThemePalette,\n useStylePresets,\n useBoxColors,\n // FlowDiagram\n FlowDiagram,\n STYLE_PRESETS,\n // SequenceDiagram\n SequenceDiagram,\n // JourneyDiagram\n JourneyDiagram,\n} from './builders';\n\nexport type {\n // Core types\n DiagramStoreOptions,\n FlowDirection,\n NodeShape,\n ParticipantType,\n TaskScore,\n // Theme types\n ThemePalette,\n StyleColors,\n StylePresets,\n BoxColors,\n // FlowDiagram types\n FlowDiagramOptions,\n FlowDiagramBuilder,\n NodeBuilder,\n EdgeBuilder,\n StyleBuilder,\n // SequenceDiagram types\n ParticipantsObject,\n SequenceDiagramOptions,\n SequenceDiagramBuilder,\n // JourneyDiagram types\n JourneyDiagramOptions,\n JourneyDiagramBuilder,\n SectionBuilder,\n} from './builders';\n","/**\n * PrettyCode Component - Dynamic Import Wrapper\n *\n * Lazy loads the heavy Prism library (~500KB) only when needed.\n * This significantly reduces the initial bundle size.\n */\n\n'use client';\n\nimport React, { lazy, Suspense } from 'react';\nimport type { Language } from 'prism-react-renderer';\n\n// Lazy load the client component\nconst PrettyCodeClient = lazy(() => import('./PrettyCode.client'));\n\n// Loading fallback component\nconst LoadingFallback = () => (\n <div className=\"relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900\">\n <div className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <div className=\"animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20\"></div>\n <span className=\"text-xs text-muted-foreground\">Loading code...</span>\n </div>\n </div>\n </div>\n);\n\nexport interface PrettyCodeProps {\n data: string | object;\n language: Language;\n className?: string;\n mode?: 'dark' | 'light';\n inline?: boolean;\n customBg?: string;\n isCompact?: boolean;\n /** Block scroll capture until user clicks (default: true) */\n scrollIsolation?: boolean;\n /**\n * Line count above which the block starts scrolling instead of growing.\n * ``undefined`` (default) = no cap, block grows to fit. Set e.g. ``50``\n * to inline short snippets and cap long ones.\n */\n maxLines?: number;\n /**\n * Visual variant:\n * - ``\"card\"`` (default) — full chrome: border, background, hover\n * toolbar (Copy + language tag), optional internal scroll. Suits\n * a standalone code block in documentation prose where the block\n * is its own surface.\n * - ``\"plain\"`` — chrome-less: no border, no background, no toolbar,\n * no internal scroll. Grows to fit its content. Use when\n * embedding inside another scroll container (e.g. the Response\n * panel) — avoids double-scroll surfaces and lets the parent\n * manage copy/language affordances.\n */\n variant?: 'card' | 'plain';\n}\n\nconst PrettyCode: React.FC<PrettyCodeProps> = (props) => {\n return (\n <Suspense fallback={<LoadingFallback />}>\n <PrettyCodeClient {...props} />\n </Suspense>\n );\n};\n\nexport default PrettyCode;\nexport type { Language };\n","import { defaultSchema } from 'rehype-sanitize';\n\n/** Sanitize schema. Typed loosely (`Record<string, unknown>`) so this\n * package's published types don't try to re-export\n * `hast-util-sanitize`'s internal Schema type — that breaks consumers\n * whose TS doesn't have the transitive dependency in scope. */\nexport type SanitizeSchema = Record<string, unknown>;\n\n// Allow-list HTML that OpenAPI descriptions commonly use — we want\n// `<b>`/`<code>`/`<br>` to render, not to appear as literal text.\n// Built on top of rehype-sanitize's default schema so we keep the\n// XSS protection (no `<script>`, no `on*` handlers, no `javascript:`\n// URLs); we just extend the tag allow-list with safe presentational\n// elements that are in wide use in API docs.\nexport const HTML_SCHEMA_BASE: SanitizeSchema = {\n ...defaultSchema,\n tagNames: [\n ...(defaultSchema.tagNames ?? []),\n 'br',\n 'b',\n 'i',\n 'u',\n 's',\n 'sub',\n 'sup',\n 'small',\n 'mark',\n 'kbd',\n 'code',\n 'pre',\n 'details',\n 'summary',\n ],\n};\n\n/** Build a sanitize schema with extra href-URL protocols allowed on\n * `<a>`. Default whitelists `http(s)/mailto/xmpp/irc(s)` — pass extras\n * here (e.g. `'cmdop'`, `'obsidian'`) to opt them in. */\nexport function buildSchema(extraProtocols: readonly string[] | undefined): SanitizeSchema {\n if (!extraProtocols || extraProtocols.length === 0) return HTML_SCHEMA_BASE;\n const baseProtocols =\n (HTML_SCHEMA_BASE as { protocols?: Record<string, string[]> }).protocols\n ?? (defaultSchema as { protocols?: Record<string, string[]> }).protocols\n ?? {};\n const baseHref = baseProtocols.href ?? ['http', 'https', 'mailto', 'xmpp', 'irc', 'ircs'];\n return {\n ...HTML_SCHEMA_BASE,\n protocols: {\n ...baseProtocols,\n href: [...baseHref, ...extraProtocols],\n },\n };\n}\n\n/** Build a `urlTransform` for ReactMarkdown that lets opted-in schemes\n * pass through verbatim. react-markdown's default strips `href` for\n * unrecognised schemes BEFORE sanitize runs — even with our extended\n * sanitize schema, custom schemes would arrive with `href=\"\"`. */\nexport function buildUrlTransform(extraProtocols: readonly string[] | undefined) {\n if (!extraProtocols || extraProtocols.length === 0) return undefined;\n const lower = extraProtocols.map((p) => p.toLowerCase() + ':');\n return (url: string): string => {\n const u = url.trim().toLowerCase();\n for (const p of lower) {\n if (u.startsWith(p)) return url;\n }\n // Fallback: replicate react-markdown's defaults for safe schemes\n // and relative paths. Anything else → empty string so the\n // anchor's href is dropped (XSS guard).\n if (\n /^(https?:|mailto:|tel:|xmpp:|irc:|ircs:|#|\\/|\\.\\/|\\.\\.\\/|\\?)/i.test(u)\n || /^[a-z0-9._~!$&'()*+,;=:@%-]+$/i.test(u)\n ) {\n return url;\n }\n return '';\n };\n}\n","import React, { memo } from 'react';\nimport { CopyButton } from '@djangocfg/ui-core/components';\nimport { useResolvedTheme } from '@djangocfg/ui-core/hooks';\nimport PrettyCode from '../../../tools/PrettyCode';\n\ninterface CodeBlockProps {\n code: string;\n language: string;\n isUser: boolean;\n isCompact?: boolean;\n}\n\n/**\n * Markdown code block. Renders <PrettyCode> directly — its own\n * FloatingToolbar already carries the language tag and Copy action.\n *\n * Earlier versions stacked an extra <CopyButton> here too, which\n * surfaced as two copy buttons on every code fence. The fallback\n * branch below still ships its own button because the plain <pre>\n * has no toolbar of its own.\n *\n * Memoised: re-renders only when `code`, `language`, `isUser` or\n * `isCompact` change. `code` is the main trigger — long code blocks\n * should not re-render when parent chat scrolls.\n */\nfunction CodeBlockRaw({ code, language }: CodeBlockProps) {\n const theme = useResolvedTheme();\n\n // Chat fences are always rendered in PrettyCode's compact mode:\n // 12px font, tighter padding, line-height 1.4. A fenced block in\n // a chat bubble shouldn't outweigh two paragraphs of body text —\n // the standalone PrettyCode story keeps the larger default for\n // docs/diff viewers.\n return (\n <div className=\"my-2\">\n <PrettyCode\n data={code}\n language={language}\n className=\"text-xs\"\n customBg=\"bg-code\"\n mode={theme}\n isCompact\n // Disable click-to-scroll-isolation in chat markdown: code\n // fences here are part of an assistant reply, not a docs\n // viewer. Forcing the user to click into a small block to\n // scroll past it interrupts the reading flow. The standalone\n // PrettyCode use cases (docs, diff viewers, long code panes)\n // keep the default `true`.\n scrollIsolation={false}\n />\n </div>\n );\n}\n\nexport const CodeBlock = memo(CodeBlockRaw);\n\n/** Simple `<pre>` fallback used when CodeBlock throws (lazy module\n * failure, missing PrettyCode peer, etc).\n *\n * Memoised: re-renders only when `code`, `language`, `isUser` or\n * `isCompact` change.\n */\nfunction CodeBlockFallbackRaw({ code, isUser }: CodeBlockProps) {\n // See CodeBlock above for the spirit of this layout — palette\n // pre-computed before render.\n const copyHoverClass = isUser\n ? 'hover:bg-white/20 text-white'\n : 'hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground';\n const copyButtonClass =\n `absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity ` +\n `h-8 w-8 ${copyHoverClass}`;\n\n return (\n <div className=\"relative group my-3\">\n <CopyButton\n value={code}\n variant=\"ghost\"\n className={copyButtonClass}\n title=\"Copy code\"\n />\n <pre className=\"p-3 rounded text-xs font-mono overflow-x-auto bg-code text-code-foreground border border-code-border\">\n <code>{code}</code>\n </pre>\n </div>\n );\n}\n\nexport const CodeBlockFallback = memo(CodeBlockFallbackRaw);\n","import React from 'react';\nimport type { Components } from 'react-markdown';\nimport Mermaid from '../../../tools/Mermaid';\nimport { CodeBlock, CodeBlockFallback } from './CodeBlock';\nimport { extractTextFromChildren } from './plainText';\n\n/**\n * Build the chat-tuned markdown component map.\n *\n * Base text size: text-sm (14px) for normal, text-xs (12px) for compact.\n * Heading sizes are scaled down a notch from the prose defaults so\n * inline-in-chat headings don't dominate.\n */\nexport function createMarkdownComponents(\n isUser: boolean = false,\n isCompact: boolean = false,\n): Components {\n const textSize = isCompact ? 'text-xs' : 'text-sm';\n const headingBase = isCompact ? 'text-sm' : 'text-base';\n const headingSm = isCompact ? 'text-xs' : 'text-sm';\n\n return {\n h1: ({ children }) => (\n <h1 className={`${headingBase} font-semibold mb-2 mt-3 first:mt-0`}>{children}</h1>\n ),\n h2: ({ children }) => (\n <h2 className={`${headingSm} font-semibold mb-2 mt-3 first:mt-0`}>{children}</h2>\n ),\n h3: ({ children }) => (\n <h3 className={`${headingSm} font-semibold mb-1 mt-2 first:mt-0`}>{children}</h3>\n ),\n h4: ({ children }) => (\n <h4 className={`${headingSm} font-semibold mb-1 mt-2 first:mt-0`}>{children}</h4>\n ),\n h5: ({ children }) => (\n <h5 className={`${headingSm} font-medium mb-1 mt-2 first:mt-0`}>{children}</h5>\n ),\n h6: ({ children }) => (\n <h6 className={`${headingSm} font-medium mb-1 mt-2 first:mt-0`}>{children}</h6>\n ),\n\n p: ({ children }) => (\n <p className={`${textSize} mb-4 last:mb-0 leading-relaxed break-words`}>{children}</p>\n ),\n\n ul: ({ children }) => (\n <ul className={`list-disc list-inside mb-2 space-y-1 ${textSize}`}>{children}</ul>\n ),\n ol: ({ children }) => (\n <ol className={`list-decimal list-inside mb-2 space-y-1 ${textSize}`}>{children}</ol>\n ),\n li: ({ children }) => <li className=\"break-words\">{children}</li>,\n\n // `target` / `rel` for external links are NOT set here — the\n // rehype-external-links plugin tags them on the rehype side, so\n // every `<a>` that sanitize let through gets the same security\n // treatment regardless of which renderer (default vs linkRules\n // override) emitted it. Doing it twice here would just duplicate\n // attributes; doing it only here would miss the linkRules path.\n a: ({ href, children, ...rest }) => (\n <a\n {...rest}\n href={href}\n className={`${textSize} ${\n isUser\n ? 'text-white/90 underline hover:text-white'\n : 'text-primary underline hover:text-primary/80'\n } transition-colors break-all`}\n >\n {children}\n </a>\n ),\n\n pre: ({ children }) => {\n let codeContent = '';\n let language = 'plaintext';\n\n if (React.isValidElement(children)) {\n const child = children;\n if (\n child.type === 'code'\n || (typeof child.type === 'function' && child.type.name === 'code')\n ) {\n const codeProps = child.props as {\n className?: string;\n children?: React.ReactNode;\n };\n const rawClassName = codeProps.className;\n language = rawClassName?.replace(/language-/, '').trim() || 'plaintext';\n codeContent = extractTextFromChildren(codeProps.children).trim();\n } else {\n codeContent = extractTextFromChildren(children).trim();\n }\n } else {\n codeContent = extractTextFromChildren(children).trim();\n }\n\n if (!codeContent) {\n return (\n <div className=\"my-3 p-3 bg-muted rounded text-sm text-muted-foreground\">\n No content available\n </div>\n );\n }\n\n if (language === 'mermaid') {\n // Inline render fits the bubble width; the Mermaid component\n // owns its own click-to-fullscreen modal which sizes against\n // the viewport, so we don't cap it here. A previous version\n // hardcoded `max-w-[600px]` and that constraint leaked into\n // the fullscreen modal too — diagram rendered at 600px in the\n // middle of an empty viewport.\n return (\n <div className=\"my-3 w-full\">\n <Mermaid chart={codeContent} isCompact={isCompact} />\n </div>\n );\n }\n\n try {\n return <CodeBlock code={codeContent} language={language} isUser={isUser} isCompact={isCompact} />;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('CodeBlock failed, using fallback:', error);\n return <CodeBlockFallback code={codeContent} language={language} isUser={isUser} isCompact={isCompact} />;\n }\n },\n\n code: ({ children, className }) => {\n // Inside <pre>: let pre handle styling.\n if (className?.includes('language-')) {\n return <code className={className}>{children}</code>;\n }\n // Inline `<code>` uses the design system's `--code-inline`\n // token. One semantic chip surface across both themes; on a\n // user bubble we still palette-switch with `text-primary-\n // foreground` because the inline chip blends INTO the bubble\n // — there's no panel boundary like a fence has. We trade a\n // perfect \"code surface\" tone here for legible body inheritance,\n // matching ChatGPT's behaviour in coloured user bubbles.\n const inlineCodeClass = isUser\n ? 'bg-primary-foreground/15 text-primary-foreground'\n : 'bg-code-inline text-code-inline-foreground';\n return (\n <code className={`px-1 py-0.5 rounded font-mono text-[0.875em] ${inlineCodeClass} break-all`}>\n {extractTextFromChildren(children)}\n </code>\n );\n },\n\n // Modern chat convention drops italic on blockquotes — italic +\n // tight bubble = hard to read. Border-left at 2px (4px reads\n // heavy in a 320–480px bubble). On the saturated user bubble we\n // use a primary-foreground tint; on the assistant bubble we use\n // the muted-foreground role for de-emphasis.\n blockquote: ({ children }) => {\n const cls = isUser\n ? 'border-primary-foreground/40 text-primary-foreground/80'\n : 'border-border text-muted-foreground';\n return (\n <blockquote className={`${textSize} border-l-2 pl-3 my-3 break-words ${cls}`}>\n {children}\n </blockquote>\n );\n },\n\n // Tables: outer wrapper handles overflow, inner `<table>`\n // inherits the chat-density text size. Borders / header use\n // semantic tokens — `border-code-border` for the assistant\n // (matches the code-fence panel for visual cohesion when both\n // appear in the same reply); primary-foreground/N for the user\n // bubble so lines read against the saturated `bg-primary`.\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-3\">\n <table className={`min-w-full ${textSize} border-collapse`}>{children}</table>\n </div>\n ),\n thead: ({ children }) => (\n <thead className={isUser ? 'bg-primary-foreground/10' : 'bg-muted/40'}>\n {children}\n </thead>\n ),\n tbody: ({ children }) => <tbody>{children}</tbody>,\n tr: ({ children }) => (\n <tr className={isUser ? 'border-b border-primary-foreground/15' : 'border-b border-border'}>\n {children}\n </tr>\n ),\n th: ({ children }) => {\n const borderCls = isUser ? 'border-primary-foreground/25' : 'border-border';\n return (\n <th className={`px-2 py-1.5 text-left font-semibold border-b ${borderCls} break-words`}>\n {children}\n </th>\n );\n },\n td: ({ children }) => <td className=\"px-2 py-1.5 break-words\">{children}</td>,\n\n // Soft separator. ChatGPT / Slack / Linear strip the visible\n // line, Claude.ai keeps a hairline. We follow Claude — present\n // but quiet. Palette switches by role so the hairline reads on\n // both surfaces.\n hr: () => (\n <hr\n className={`my-4 border-0 h-px ${\n isUser ? 'bg-primary-foreground/20' : 'bg-border'\n }`}\n />\n ),\n\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n em: ({ children }) => <em className=\"italic\">{children}</em>,\n };\n}\n","import React, { memo } from 'react';\n\ninterface CollapseToggleProps {\n isCollapsed: boolean;\n onClick: () => void;\n readMoreLabel: string;\n showLessLabel: string;\n isUser: boolean;\n isCompact: boolean;\n}\n\n/** \"Read more...\" / \"Show less\" button.\n *\n * Memoised: re-renders only when `isCollapsed`, `onClick`, `readMoreLabel`,\n * `showLessLabel`, `isUser` or `isCompact` change. `onClick` is compared\n * by reference — callers should stabilise it with useCallback.\n */\nfunction CollapseToggleRaw({\n isCollapsed,\n onClick,\n readMoreLabel,\n showLessLabel,\n isUser,\n isCompact,\n}: CollapseToggleProps) {\n const textSize = isCompact ? 'text-xs' : 'text-sm';\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={`\n ${textSize} font-medium cursor-pointer\n transition-colors duration-200\n ${isUser ? 'text-white/80 hover:text-white' : 'text-primary hover:text-primary/80'}\n inline-flex items-center gap-1\n mt-1\n `}\n >\n {isCollapsed ? (\n <>\n {readMoreLabel}\n <Chevron direction=\"down\" />\n </>\n ) : (\n <>\n {showLessLabel}\n <Chevron direction=\"up\" />\n </>\n )}\n </button>\n );\n};\n\nconst Chevron = memo(function Chevron({ direction }: { direction: 'up' | 'down' }) {\n return (\n <svg className=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d={direction === 'down' ? 'M19 9l-7 7-7-7' : 'M5 15l7-7 7 7'}\n />\n </svg>\n );\n});\n\nexport const CollapseToggle = memo(CollapseToggleRaw);\n","import React from 'react';\nimport type { ComponentProps, ComponentType } from 'react';\nimport type { Components } from 'react-markdown';\nimport type { LinkRule } from './types';\n\n// react-markdown's `Components['a']` is `keyof IntrinsicElements | ComponentType<…>`,\n// so it isn't necessarily a function we can directly call. This is the\n// component-shaped variant — what callers practically pass when they\n// override `a`.\ntype AComponent = ComponentType<ComponentProps<'a'>>;\n\n/** Run every rule's `preprocess` hook in order. Errors in a single\n * rule are logged and skipped — the other rules still run. */\nexport function applyPreprocess(\n source: string,\n rules: readonly LinkRule[] | undefined,\n): string {\n if (!rules || rules.length === 0) return source;\n let s = source;\n for (const rule of rules) {\n if (!rule.preprocess) continue;\n try {\n s = rule.preprocess(s);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(\n `[MarkdownMessage] linkRule \"${rule.name ?? '(anonymous)'}\" preprocess threw; skipping`,\n err,\n );\n }\n }\n return s;\n}\n\n/** Union of `extraHrefProtocols` and any `protocols` declared by rules. */\nexport function collectProtocols(\n extraHrefProtocols: readonly string[] | undefined,\n rules: readonly LinkRule[] | undefined,\n): readonly string[] | undefined {\n const set = new Set<string>();\n if (extraHrefProtocols) for (const p of extraHrefProtocols) set.add(p);\n if (rules) {\n for (const r of rules) {\n if (r.protocols) for (const p of r.protocols) set.add(p);\n }\n }\n return set.size === 0 ? undefined : Array.from(set);\n}\n\n/** Build a custom `a` renderer that dispatches to the first matching\n * rule, falling through to `callerA` (or the built-in chat anchor)\n * for anything no rule claims. */\nexport function buildLinkRulesComponent(\n rules: readonly LinkRule[],\n isUser: boolean,\n callerA: NonNullable<Components['a']> | undefined,\n): NonNullable<Components['a']> {\n const Renderer: AComponent = (props) => {\n const { href, children } = props;\n if (typeof href === 'string') {\n for (const rule of rules) {\n if (rule.match(href)) {\n return React.createElement(\n React.Fragment,\n null,\n rule.render({ href, children, isUser }),\n );\n }\n }\n }\n // Defer to the caller's `a` override if any. We only call it when\n // it's a function/component — string-form intrinsic overrides\n // (`'a' | 'span' | …`) aren't a thing react-markdown supports for\n // tag overrides, but the type still admits the union, so guard.\n if (callerA && typeof callerA === 'function') {\n const Caller = callerA as AComponent;\n return React.createElement(Caller, props);\n }\n // Fall through to the built-in anchor by rendering a plain `<a>`.\n return React.createElement('a', props, children);\n };\n return Renderer as NonNullable<Components['a']>;\n}\n","'use client';\n\nimport React, { memo } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport rehypeExternalLinks from 'rehype-external-links';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeSanitize from 'rehype-sanitize';\nimport remarkBreaks from 'remark-breaks';\nimport remarkEmoji from 'remark-emoji';\nimport remarkGfm from 'remark-gfm';\nimport remarkSmartypants from 'remark-smartypants';\nimport type { Components } from 'react-markdown';\n\nimport { useCollapsibleContent } from '../useCollapsibleContent';\nimport type { MarkdownMessageProps } from './types';\nimport { buildSchema, buildUrlTransform } from './sanitize';\nimport { looksLikePlainProse } from './plainText';\nimport { createMarkdownComponents } from './components';\nimport { CollapseToggle } from './CollapseToggle';\nimport { applyPreprocess, buildLinkRulesComponent, collectProtocols } from './linkRules';\n\n/**\n * MarkdownMessage — chat-tuned markdown renderer.\n *\n * Features:\n * - GitHub Flavored Markdown (GFM) via remark-gfm\n * - Syntax-highlighted code blocks with Copy button\n * - Mermaid diagram rendering (` ```mermaid ` fence)\n * - Tables, lists, blockquotes scaled for chat density\n * - User vs assistant styling modes (`isUser`)\n * - Plain-text fast path: skips ReactMarkdown when content has no\n * markdown syntax (cheaper render, preserves newlines via CSS)\n * - Optional collapsible \"Read more...\" for long messages\n *\n * Custom URL schemes (chat mentions, deep-links, custom file viewers)\n * are best handled with the declarative `linkRules` prop — see the\n * type definition in `./types.ts` and the storybook for examples.\n *\n * @example\n * ```tsx\n * <MarkdownMessage content=\"# Hello\\n\\nThis is **bold** text.\" />\n *\n * // User message styling\n * <MarkdownMessage content=\"Some content\" isUser />\n *\n * // Custom URL scheme via linkRules\n * <MarkdownMessage\n * content=\"Talk to [Vps-audi](cmdop://machine/abc-123)\"\n * linkRules={[machineMentionRule]}\n * />\n * ```\n *\n * Memoised: re-renders only when props change. `content` is the main\n * trigger — all other props (className, isUser, isCompact, etc.) are\n * compared by value/reference. `onCollapseChange` is compared by\n * reference — callers should stabilise it with useCallback.\n */\nfunction MarkdownMessageRaw({\n content,\n className = '',\n isUser = false,\n isCompact = false,\n plainText,\n customComponents,\n extraHrefProtocols,\n linkRules,\n collapsible = false,\n maxLength,\n maxLines,\n readMoreLabel = 'Read more...',\n showLessLabel = 'Show less',\n defaultExpanded = false,\n onCollapseChange,\n}: MarkdownMessageProps) {\n // Pre-process content through any rules that requested it. Done\n // before trim so a rule can rewrite multi-line shapes too.\n const preprocessed = React.useMemo(\n () => applyPreprocess(content, linkRules),\n [content, linkRules],\n );\n\n // Union of `extraHrefProtocols` and any `protocols` declared by rules.\n const effectiveProtocols = React.useMemo(\n () => collectProtocols(extraHrefProtocols, linkRules),\n [extraHrefProtocols, linkRules],\n );\n\n // Effective custom components: merge linkRules' synthesized `a`\n // renderer with any caller-provided `customComponents`. linkRules\n // wins when both target the same href (rule is the more specific\n // declarative claim by design).\n const effectiveCustomComponents = React.useMemo<Partial<Components> | undefined>(() => {\n if (!linkRules || linkRules.length === 0) return customComponents;\n const callerA = customComponents?.a;\n const aRenderer = buildLinkRulesComponent(linkRules, isUser, callerA);\n return { ...(customComponents ?? {}), a: aRenderer };\n }, [customComponents, linkRules, isUser]);\n\n const trimmedContent = preprocessed.trim();\n\n // Collapsible content logic — defaults kick in only when enabled.\n const collapsibleOptions = React.useMemo(() => {\n if (!collapsible) return {};\n return {\n maxLength: maxLength ?? 1000,\n maxLines: maxLines ?? 10,\n defaultExpanded,\n };\n }, [collapsible, maxLength, maxLines, defaultExpanded]);\n\n const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } =\n useCollapsibleContent(trimmedContent, collapsible ? collapsibleOptions : {});\n\n React.useEffect(() => {\n if (collapsible && shouldCollapse && onCollapseChange) {\n onCollapseChange(isCollapsed);\n }\n }, [isCollapsed, collapsible, shouldCollapse, onCollapseChange]);\n\n const components = React.useMemo(() => {\n const base = createMarkdownComponents(isUser, isCompact);\n return effectiveCustomComponents ? { ...base, ...effectiveCustomComponents } : base;\n }, [isUser, isCompact, effectiveCustomComponents]);\n\n const schema = React.useMemo(() => buildSchema(effectiveProtocols), [effectiveProtocols]);\n const urlTransform = React.useMemo(\n () => buildUrlTransform(effectiveProtocols),\n [effectiveProtocols],\n );\n\n const textSizeClass = isCompact ? 'text-xs' : 'text-sm';\n const proseClass = isCompact ? 'prose-xs' : 'prose-sm';\n\n // Resolve plain-vs-markdown branch:\n // 1. Caller-passed `plainText` wins outright (explicit beats clever).\n // 2. Caller-supplied non-`a` customComponents force the markdown\n // pipeline — those overrides only matter on real markdown nodes.\n // 3. Otherwise auto-detect via `looksLikePlainProse` (short,\n // single-paragraph, no markdown markers). This is the chat-bubble\n // WhatsApp/Telegram heuristic — \"would the human have written\n // this in one keystroke?\".\n const customComponentsBeyondLinks = React.useMemo(() => {\n if (!customComponents) return false;\n return Object.keys(customComponents).some((k) => k !== 'a');\n }, [customComponents]);\n const isPlainText = plainText !== undefined\n ? plainText\n : !customComponentsBeyondLinks && looksLikePlainProse(displayContent);\n\n if (isPlainText) {\n // <div> + whitespace-pre-wrap: respects newlines AND collapses\n // double spaces, which is what users mean when they hit Enter\n // twice. <span> would break flow inside a flex bubble.\n //\n // leading-snug (1.375), not leading-relaxed (1.625) — `pre-wrap`\n // makes every `\\n` a hard line break, so the relaxed leading\n // turns multi-line user messages into airy ladders. snug matches\n // WhatsApp/Telegram bubble density.\n return (\n <div\n className={`${textSizeClass} font-normal antialiased leading-snug break-words whitespace-pre-wrap ${className}`}\n >\n {displayContent}\n {collapsible && shouldCollapse && (\n <>\n {isCollapsed && '... '}\n <CollapseToggle\n isCollapsed={isCollapsed}\n onClick={toggleCollapsed}\n readMoreLabel={readMoreLabel}\n showLessLabel={showLessLabel}\n isUser={isUser}\n isCompact={isCompact}\n />\n </>\n )}\n </div>\n );\n }\n\n return (\n <div className={className}>\n <div\n className={`\n prose ${proseClass} max-w-none break-words overflow-hidden ${textSizeClass} font-normal antialiased\n ${isUser ? 'prose-invert' : 'dark:prose-invert'}\n [&>*]:leading-relaxed\n [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\n [&_p]:my-2\n [&_ul]:my-2 [&_ol]:my-2 [&_ul]:pl-5 [&_ol]:pl-5\n [&_li]:my-1 [&_li>p]:my-0\n [&_h1]:mt-4 [&_h1]:mb-2 [&_h1]:text-base [&_h1]:font-semibold\n [&_h2]:mt-3.5 [&_h2]:mb-1.5 [&_h2]:text-[15px] [&_h2]:font-semibold\n [&_h3]:mt-3 [&_h3]:mb-1 [&_h3]:text-sm [&_h3]:font-medium\n [&_h4]:mt-3 [&_h4]:mb-1 [&_h4]:text-sm [&_h4]:font-medium\n `}\n style={{\n // Inherit colors from parent — fixes issues with external\n // CSS variables overriding prose tokens.\n '--tw-prose-body': 'inherit',\n '--tw-prose-headings': 'inherit',\n '--tw-prose-bold': 'inherit',\n '--tw-prose-links': 'inherit',\n color: 'inherit',\n } as React.CSSProperties}\n >\n <ReactMarkdown\n // Remark plugin order is load-bearing:\n // 1. `remark-gfm` — tables, strikethrough, autolinks, task lists.\n // 2. `remark-breaks` — chat convention: single `\\n` → `<br>`\n // (ChatGPT / Slack / Discord / Linear). CommonMark's\n // default would collapse those into one paragraph and\n // LLM punchlines / poems / dialogue would render as a\n // run-on line. Goes BEFORE smartypants so quotes that\n // land at line breaks still get the curly treatment.\n // 3. `remark-smartypants` — typographic substitutions:\n // \"...\" → …, -- → —, \"x\" → \"x\". Cheap \"humanized\"\n // polish à la Medium / Substack.\n // 4. `remark-emoji` — `:smile:` → 😄 (GitHub / Linear\n // shortcode style). Leaves Unicode emoji untouched.\n remarkPlugins={[remarkGfm, remarkBreaks, remarkSmartypants, remarkEmoji]}\n // rehype-raw parses inline HTML in the source; rehype-sanitize\n // (with our extended schema) runs after to keep XSS guards\n // (no scripts, no on* handlers, no javascript: urls).\n // rehype-external-links runs LAST so it tags every <a> that\n // sanitize let through — externals get target=_blank +\n // rel=noopener noreferrer in one pass, instead of every\n // custom `a` renderer reimplementing the rule.\n rehypePlugins={[\n rehypeRaw,\n [rehypeSanitize, schema],\n [rehypeExternalLinks, { target: '_blank', rel: ['noopener', 'noreferrer'] }],\n ]}\n components={components}\n // urlTransform runs in remark-rehype before sanitize. Without\n // overriding it, react-markdown's default strips `href` for\n // unknown schemes — making our extended sanitize whitelist\n // moot. Only set when the caller opted into extra protocols.\n urlTransform={urlTransform}\n >\n {displayContent}\n </ReactMarkdown>\n </div>\n {collapsible && shouldCollapse && (\n <CollapseToggle\n isCollapsed={isCollapsed}\n onClick={toggleCollapsed}\n readMoreLabel={readMoreLabel}\n showLessLabel={showLessLabel}\n isUser={isUser}\n isCompact={isCompact}\n />\n )}\n </div>\n );\n};\n\nexport const MarkdownMessage = memo(MarkdownMessageRaw);\n\nexport default MarkdownMessage;\n","'use client';\n\nimport React, { memo } from 'react';\nimport { CopyButton } from '@djangocfg/ui-core/components';\n\ninterface ActionRowProps {\n /** Raw text to copy — pass the same source string used for render. */\n value: string;\n /** Bubble side. Just controls flex alignment; nothing is mirrored. */\n isUser: boolean;\n /**\n * Whether the row is currently shown. Owner-controlled (typically\n * `<ChatMessageRow>` toggles this on hover with a small close delay).\n * The component is intentionally dumb about visibility — owners\n * have full control over reveal logic (hover, focus, always-on,\n * touch behaviour, etc.).\n */\n visible: boolean;\n}\n\n// Action row that lives directly under a chat bubble.\n// Visibility is fully owner-controlled via `visible`.\n//\n// We render at `opacity-0` (not `display:none`) so the fade in/out\n// stays smooth across re-renders. While invisible we drop pointer\n// events so a hidden row can't intercept clicks meant for the page\n// underneath.\n//\n// Memoised: re-renders only when `value`, `isUser` or `visible` change.\n// All props are primitives, so default shallow comparison is sufficient.\nfunction ActionRowRaw({ value, isUser, visible }: ActionRowProps) {\n return (\n <div\n className={`flex ${isUser ? 'justify-end' : 'justify-start'}\n transition-opacity duration-150\n ${visible ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}\n >\n <CopyButton\n value={value}\n size=\"icon\"\n variant=\"ghost\"\n iconClassName=\"h-3.5 w-3.5\"\n className=\"h-7 w-7 text-muted-foreground hover:text-foreground\"\n // Hidden rows must not be reachable via Tab — otherwise\n // keyboard users land on an invisible button.\n tabIndex={visible ? 0 : -1}\n aria-hidden={!visible}\n />\n </div>\n );\n}\n\nexport const ActionRow = memo(ActionRowRaw);\n","'use client';\n\nimport React, { memo, useCallback, useEffect, useRef, useState } from 'react';\nimport { useMediaQuery } from '@djangocfg/ui-core/hooks';\n\ninterface ChatMessageRowProps {\n /** Side of the conversation — drives flex alignment and `isUser`\n * passed to `actions`. */\n isUser: boolean;\n /** The bubble (your own JSX). Anything goes — `<MarkdownMessage>`,\n * custom card, multi-element composition. */\n children: React.ReactNode;\n /** Render-prop for the action row. Receives `visible` so the row\n * knows when to fade in/out. Render `null` to opt out. */\n actions?: (visible: boolean, isUser: boolean) => React.ReactNode;\n /** Close delay in ms after the cursor leaves the row. Long enough\n * to bridge cursor travel from bubble → action button without\n * flicker. Default 250ms (Radix Tooltip-ish). */\n closeDelayMs?: number;\n /** Optional class on the column container. */\n className?: string;\n}\n\n// Owner of the bubble + action row layout.\n//\n// Why a state-based hover instead of `group-hover` CSS:\n// - CSS-only hover bridges break when the cursor crosses gaps\n// between the bubble and the (initially-invisible) row — the\n// row's `pointer-events-none` lets the cursor \"fall through\",\n// `group-hover` flips off, the row vanishes mid-travel.\n// - State + a small close timeout gives Radix-Tooltip-style\n// stability: enter shows immediately, leave waits N ms.\n// - On touch (`@media (hover:none)`) hover doesn't exist; we\n// always pass `visible={true}` so the affordance is reachable.\n//\n// The action row is rendered **absolutely** under the bubble so\n// hidden rows don't allocate vertical space — no dead-air gap\n// between consecutive messages.\n//\n// Memoised: re-renders only when `isUser`, `children`, `actions`,\n// `closeDelayMs` or `className` change. `actions` render-prop is\n// compared by reference — callers should stabilise it with useCallback.\nfunction ChatMessageRowRaw({\n isUser,\n children,\n actions,\n closeDelayMs = 250,\n className = '',\n}: ChatMessageRowProps) {\n const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');\n const [hovered, setHovered] = useState(false);\n const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancelClose = useCallback(() => {\n if (closeTimer.current) {\n clearTimeout(closeTimer.current);\n closeTimer.current = null;\n }\n }, []);\n\n const open = useCallback(() => {\n cancelClose();\n setHovered(true);\n }, [cancelClose]);\n\n const scheduleClose = useCallback(() => {\n cancelClose();\n closeTimer.current = setTimeout(() => setHovered(false), closeDelayMs);\n }, [cancelClose, closeDelayMs]);\n\n useEffect(() => () => cancelClose(), [cancelClose]);\n\n // Touch: always-visible. Hover: state-driven.\n const visible = isTouch || hovered;\n\n // On touch, `static` positioning so the row claims real layout\n // space (otherwise an absolute always-visible row would still\n // overlap the next message). On hover devices, `absolute` so the\n // hidden row doesn't leave dead air between bubbles.\n const rowPositionClass = isTouch ? 'static mt-1' : 'absolute top-full';\n const rowSideClass = isUser ? 'right-0' : 'left-0';\n\n return (\n <div\n className={`relative flex flex-col ${isUser ? 'items-end' : 'items-start'} ${className}`}\n onPointerEnter={isTouch ? undefined : open}\n onPointerLeave={isTouch ? undefined : scheduleClose}\n onFocusCapture={open}\n onBlurCapture={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) scheduleClose();\n }}\n >\n {children}\n {actions && (\n <div className={`${rowPositionClass} ${rowSideClass}`}>\n {actions(visible, isUser)}\n </div>\n )}\n </div>\n );\n}\n\nexport const ChatMessageRow = memo(ChatMessageRowRaw);\n"]}
@@ -1,6 +1,6 @@
1
1
  import { __name } from './chunk-N2XQF2OL.mjs';
2
2
  import * as React from 'react';
3
- import { createContext, useMemo, useReducer, useRef, useCallback, useEffect, Fragment as Fragment$1 } from 'react';
3
+ import { createContext, memo, useMemo, useReducer, useRef, useCallback, useEffect, Fragment as Fragment$1 } from 'react';
4
4
  import { cn } from '@djangocfg/ui-core/lib';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { ChevronDown, ChevronRight, FolderOpen, Folder, File, Loader2, Search, X } from 'lucide-react';
@@ -550,7 +550,7 @@ function TreeProvider(props) {
550
550
  return /* @__PURE__ */ jsx(TreeContext.Provider, { value, children });
551
551
  }
552
552
  __name(TreeProvider, "TreeProvider");
553
- function TreeChevron({ isExpanded, isFolder, className }) {
553
+ function TreeChevronRaw({ isExpanded, isFolder, className }) {
554
554
  const { appearance } = useTreeContext();
555
555
  const size = { width: "var(--tree-icon-size)", height: "var(--tree-icon-size)" };
556
556
  if (!isFolder) {
@@ -577,8 +577,9 @@ function TreeChevron({ isExpanded, isFolder, className }) {
577
577
  }
578
578
  );
579
579
  }
580
- __name(TreeChevron, "TreeChevron");
581
- function TreeIcon({ isFolder, isExpanded, className }) {
580
+ __name(TreeChevronRaw, "TreeChevronRaw");
581
+ var TreeChevron = memo(TreeChevronRaw);
582
+ function TreeIconRaw({ isFolder, isExpanded, className }) {
582
583
  const { appearance } = useTreeContext();
583
584
  const Icon = isFolder ? isExpanded ? FolderOpen : Folder : File;
584
585
  return /* @__PURE__ */ jsx(
@@ -595,7 +596,8 @@ function TreeIcon({ isFolder, isExpanded, className }) {
595
596
  }
596
597
  );
597
598
  }
598
- __name(TreeIcon, "TreeIcon");
599
+ __name(TreeIconRaw, "TreeIconRaw");
600
+ var TreeIcon = memo(TreeIconRaw);
599
601
  function TreeIndentGuides({ level, indent }) {
600
602
  const { appearance } = useTreeContext();
601
603
  if (level <= 0) return null;
@@ -617,7 +619,7 @@ function TreeIndentGuides({ level, indent }) {
617
619
  );
618
620
  }
619
621
  __name(TreeIndentGuides, "TreeIndentGuides");
620
- function TreeLabel({ children, isMatchingSearch, className }) {
622
+ function TreeLabelRaw({ children, isMatchingSearch, className }) {
621
623
  return /* @__PURE__ */ jsx(
622
624
  "span",
623
625
  {
@@ -631,8 +633,9 @@ function TreeLabel({ children, isMatchingSearch, className }) {
631
633
  }
632
634
  );
633
635
  }
634
- __name(TreeLabel, "TreeLabel");
635
- function TreeRow({ row, className }) {
636
+ __name(TreeLabelRaw, "TreeLabelRaw");
637
+ var TreeLabel = memo(TreeLabelRaw);
638
+ function TreeRowRaw({ row, className }) {
636
639
  const ctx = useTreeContext();
637
640
  const {
638
641
  appearance,
@@ -765,7 +768,8 @@ function TreeRow({ row, className }) {
765
768
  }
766
769
  return trigger;
767
770
  }
768
- __name(TreeRow, "TreeRow");
771
+ __name(TreeRowRaw, "TreeRowRaw");
772
+ var TreeRow = memo(TreeRowRaw);
769
773
  function TreeEmpty({ children, className }) {
770
774
  return /* @__PURE__ */ jsx(
771
775
  "div",
@@ -1266,5 +1270,5 @@ __name(TreeRootShell, "TreeRootShell");
1266
1270
  var TreeRoot_default = TreeRoot;
1267
1271
 
1268
1272
  export { DEFAULT_TREE_APPEARANCE, DEFAULT_TREE_LABELS, TreeChevron, TreeContent, TreeEmpty, TreeIcon, TreeIndentGuides, TreeLabel, TreeProvider, TreeRoot, TreeRoot_default, TreeRow, TreeSearchInput, appearanceToStyle, clearTreeState, createChildCache, flattenTree, loadTreeState, resolveAppearance, resolveChildren, saveTreeState, useTreeActions, useTreeContext, useTreeExpansion, useTreeFocus, useTreeKeyboard, useTreeLabels, useTreeRows, useTreeSearch, useTreeSelection, useTreeTypeAhead };
1269
- //# sourceMappingURL=chunk-G5IEC7SR.mjs.map
1270
- //# sourceMappingURL=chunk-G5IEC7SR.mjs.map
1273
+ //# sourceMappingURL=chunk-ZL7FH4NW.mjs.map
1274
+ //# sourceMappingURL=chunk-ZL7FH4NW.mjs.map