@djangocfg/ui-tools 2.1.301 → 2.1.303

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 (30) hide show
  1. package/dist/{DocsLayout-MWRKNFXR.mjs → DocsLayout-6ECALRLD.mjs} +3 -3
  2. package/dist/{DocsLayout-MWRKNFXR.mjs.map → DocsLayout-6ECALRLD.mjs.map} +1 -1
  3. package/dist/{DocsLayout-NWJUF42A.cjs → DocsLayout-ASPSECYR.cjs} +48 -48
  4. package/dist/{DocsLayout-NWJUF42A.cjs.map → DocsLayout-ASPSECYR.cjs.map} +1 -1
  5. package/dist/{Mermaid.client-XFQ74OYN.mjs → Mermaid.client-SXRRI2YW.mjs} +43 -6
  6. package/dist/Mermaid.client-SXRRI2YW.mjs.map +1 -0
  7. package/dist/{Mermaid.client-RSWUUHIL.cjs → Mermaid.client-W76R5AKJ.cjs} +43 -6
  8. package/dist/Mermaid.client-W76R5AKJ.cjs.map +1 -0
  9. package/dist/{chunk-CKD7GNE5.mjs → chunk-K35OF7OB.mjs} +88 -52
  10. package/dist/chunk-K35OF7OB.mjs.map +1 -0
  11. package/dist/{chunk-SEXWBCLX.cjs → chunk-PFKR6ZPZ.cjs} +88 -52
  12. package/dist/chunk-PFKR6ZPZ.cjs.map +1 -0
  13. package/dist/index.cjs +11 -11
  14. package/dist/index.d.cts +20 -0
  15. package/dist/index.d.ts +20 -0
  16. package/dist/index.mjs +5 -5
  17. package/package.json +6 -6
  18. package/src/components/markdown/MarkdownMessage/CodeBlock.tsx +53 -42
  19. package/src/components/markdown/MarkdownMessage/MarkdownMessage.story.tsx +422 -0
  20. package/src/components/markdown/MarkdownMessage/MarkdownMessage.tsx +38 -11
  21. package/src/components/markdown/MarkdownMessage/components.tsx +69 -14
  22. package/src/components/markdown/MarkdownMessage/plainText.ts +33 -0
  23. package/src/components/markdown/MarkdownMessage/types.ts +13 -0
  24. package/src/tools/Mermaid/Mermaid.client.tsx +10 -1
  25. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +76 -3
  26. package/src/tools/Mermaid/index.tsx +7 -0
  27. package/dist/Mermaid.client-RSWUUHIL.cjs.map +0 -1
  28. package/dist/Mermaid.client-XFQ74OYN.mjs.map +0 -1
  29. package/dist/chunk-CKD7GNE5.mjs.map +0 -1
  30. package/dist/chunk-SEXWBCLX.cjs.map +0 -1
@@ -150,6 +150,17 @@ function extractTextFromChildren(children) {
150
150
  return "";
151
151
  }
152
152
  chunkWGEGR3DF_cjs.__name(extractTextFromChildren, "extractTextFromChildren");
153
+ function looksLikePlainProse(text) {
154
+ const trimmed = text.trim();
155
+ if (trimmed.length === 0) return true;
156
+ if (trimmed.length > 500) return false;
157
+ if (/\n\s*\n/.test(trimmed)) return false;
158
+ const newlineCount = (trimmed.match(/\n/g) || []).length;
159
+ if (newlineCount > 4) return false;
160
+ if (hasMarkdownSyntax(trimmed)) return false;
161
+ return true;
162
+ }
163
+ chunkWGEGR3DF_cjs.__name(looksLikePlainProse, "looksLikePlainProse");
153
164
  function hasMarkdownSyntax(text) {
154
165
  if (text.trim().includes("\n")) return true;
155
166
  if (/<\/?[a-zA-Z][a-zA-Z0-9-]*(\s[^>]*)?\/?>/.test(text)) return true;
@@ -188,7 +199,7 @@ function hasMarkdownSyntax(text) {
188
199
  return patterns.some((p) => p.test(text));
189
200
  }
190
201
  chunkWGEGR3DF_cjs.__name(hasMarkdownSyntax, "hasMarkdownSyntax");
191
- var MermaidClient = React6.lazy(() => import('./Mermaid.client-RSWUUHIL.cjs'));
202
+ var MermaidClient = React6.lazy(() => import('./Mermaid.client-W76R5AKJ.cjs'));
192
203
  var LoadingFallback = /* @__PURE__ */ chunkWGEGR3DF_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");
193
204
  var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((props) => {
194
205
  return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback, {}), children: /* @__PURE__ */ jsxRuntime.jsx(MermaidClient, { ...props }) });
@@ -251,54 +262,38 @@ function buildUrlTransform(extraProtocols) {
251
262
  };
252
263
  }
253
264
  chunkWGEGR3DF_cjs.__name(buildUrlTransform, "buildUrlTransform");
254
- var CodeBlock = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ code, language, isUser, isCompact = false }) => {
265
+ var CodeBlock = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ code, language, isCompact = false }) => {
255
266
  const theme = hooks.useResolvedTheme();
267
+ const textSizeClass = isCompact ? "text-xs" : "text-sm";
268
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3", children: /* @__PURE__ */ jsxRuntime.jsx(
269
+ PrettyCode_default,
270
+ {
271
+ data: code,
272
+ language,
273
+ className: textSizeClass,
274
+ customBg: "bg-code",
275
+ mode: theme,
276
+ isCompact,
277
+ scrollIsolation: false
278
+ }
279
+ ) });
280
+ }, "CodeBlock");
281
+ var CodeBlockFallback = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ code, isUser }) => {
282
+ const copyHoverClass = isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground";
283
+ const copyButtonClass = `absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8 ${copyHoverClass}`;
256
284
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group my-3", children: [
257
285
  /* @__PURE__ */ jsxRuntime.jsx(
258
286
  components.CopyButton,
259
287
  {
260
288
  value: code,
261
289
  variant: "ghost",
262
- className: `
263
- absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity
264
- h-8 w-8
265
- ${isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground"}
266
- `,
290
+ className: copyButtonClass,
267
291
  title: "Copy code"
268
292
  }
269
293
  ),
270
- /* @__PURE__ */ jsxRuntime.jsx(
271
- PrettyCode_default,
272
- {
273
- data: code,
274
- language,
275
- className: isCompact ? "text-xs" : "text-sm",
276
- customBg: isUser ? "bg-white/10" : "bg-muted dark:bg-muted",
277
- mode: theme,
278
- isCompact
279
- }
280
- )
294
+ /* @__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 }) })
281
295
  ] });
282
- }, "CodeBlock");
283
- var CodeBlockFallback = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ code, isUser }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group my-3", children: [
284
- /* @__PURE__ */ jsxRuntime.jsx(
285
- components.CopyButton,
286
- {
287
- value: code,
288
- variant: "ghost",
289
- className: `
290
- absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity
291
- h-8 w-8
292
- ${isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground"}
293
- `,
294
- title: "Copy code"
295
- }
296
- ),
297
- /* @__PURE__ */ jsxRuntime.jsx("pre", { className: `
298
- p-3 rounded text-xs font-mono overflow-x-auto
299
- ${isUser ? "bg-white/10 text-white" : "bg-muted text-foreground"}
300
- `, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: code }) })
301
- ] }), "CodeBlockFallback");
296
+ }, "CodeBlockFallback");
302
297
  function createMarkdownComponents(isUser = false, isCompact = false) {
303
298
  const textSize = isCompact ? "text-xs" : "text-sm";
304
299
  const headingBase = isCompact ? "text-sm" : "text-base";
@@ -344,7 +339,7 @@ function createMarkdownComponents(isUser = false, isCompact = false) {
344
339
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3 p-3 bg-muted rounded text-sm text-muted-foreground", children: "No content available" });
345
340
  }
346
341
  if (language === "mermaid") {
347
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3 max-w-full overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(Mermaid_default, { chart: codeContent, className: "max-w-[600px] mx-auto", isCompact }) });
342
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(Mermaid_default, { chart: codeContent, isCompact }) });
348
343
  }
349
344
  try {
350
345
  return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: codeContent, language, isUser, isCompact });
@@ -357,16 +352,43 @@ function createMarkdownComponents(isUser = false, isCompact = false) {
357
352
  if (className?.includes("language-")) {
358
353
  return /* @__PURE__ */ jsxRuntime.jsx("code", { className, children });
359
354
  }
360
- return /* @__PURE__ */ jsxRuntime.jsx("code", { className: "px-1.5 py-0.5 rounded text-xs font-mono bg-muted text-foreground break-all", children: extractTextFromChildren(children) });
355
+ const inlineCodeClass = isUser ? "bg-primary-foreground/15 text-primary-foreground" : "bg-code-inline text-code-inline-foreground";
356
+ return /* @__PURE__ */ jsxRuntime.jsx("code", { className: `px-1 py-0.5 rounded font-mono text-[0.875em] ${inlineCodeClass} break-all`, children: extractTextFromChildren(children) });
361
357
  }, "code"),
362
- blockquote: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: `${textSize} border-l-2 border-border pl-3 my-2 italic text-muted-foreground break-words`, children }), "blockquote"),
358
+ // Modern chat convention drops italic on blockquotes italic +
359
+ // tight bubble = hard to read. Border-left at 2px (4px reads
360
+ // heavy in a 320–480px bubble). On the saturated user bubble we
361
+ // use a primary-foreground tint; on the assistant bubble we use
362
+ // the muted-foreground role for de-emphasis.
363
+ blockquote: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => {
364
+ const cls = isUser ? "border-primary-foreground/40 text-primary-foreground/80" : "border-border text-muted-foreground";
365
+ return /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: `${textSize} border-l-2 pl-3 my-3 break-words ${cls}`, children });
366
+ }, "blockquote"),
367
+ // Tables: outer wrapper handles overflow, inner `<table>`
368
+ // inherits the chat-density text size. Borders / header use
369
+ // semantic tokens — `border-code-border` for the assistant
370
+ // (matches the code-fence panel for visual cohesion when both
371
+ // appear in the same reply); primary-foreground/N for the user
372
+ // bubble so lines read against the saturated `bg-primary`.
363
373
  table: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto my-3", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: `min-w-full ${textSize} border-collapse`, children }) }), "table"),
364
- thead: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-muted/50", children }), "thead"),
374
+ thead: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("thead", { className: isUser ? "bg-primary-foreground/10" : "bg-muted/40", children }), "thead"),
365
375
  tbody: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { children }), "tbody"),
366
- tr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-border/50", children }), "tr"),
367
- th: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-2 py-1 text-left font-medium break-words", children }), "th"),
368
- td: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1 break-words", children }), "td"),
369
- hr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-3 border-0 h-px bg-border" }), "hr"),
376
+ tr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: isUser ? "border-b border-primary-foreground/15" : "border-b border-border", children }), "tr"),
377
+ th: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => {
378
+ const borderCls = isUser ? "border-primary-foreground/25" : "border-border";
379
+ return /* @__PURE__ */ jsxRuntime.jsx("th", { className: `px-2 py-1.5 text-left font-semibold border-b ${borderCls} break-words`, children });
380
+ }, "th"),
381
+ td: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1.5 break-words", children }), "td"),
382
+ // Soft separator. ChatGPT / Slack / Linear strip the visible
383
+ // line, Claude.ai keeps a hairline. We follow Claude — present
384
+ // but quiet. Palette switches by role so the hairline reads on
385
+ // both surfaces.
386
+ hr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx(
387
+ "hr",
388
+ {
389
+ className: `my-4 border-0 h-px ${isUser ? "bg-primary-foreground/20" : "bg-border"}`
390
+ }
391
+ ), "hr"),
370
392
  strong: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold", children }), "strong"),
371
393
  em: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("em", { className: "italic", children }), "em")
372
394
  };
@@ -471,6 +493,7 @@ var MarkdownMessage = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
471
493
  className = "",
472
494
  isUser = false,
473
495
  isCompact = false,
496
+ plainText,
474
497
  customComponents,
475
498
  extraHrefProtocols,
476
499
  linkRules,
@@ -522,12 +545,16 @@ var MarkdownMessage = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
522
545
  );
523
546
  const textSizeClass = isCompact ? "text-xs" : "text-sm";
524
547
  const proseClass = isCompact ? "prose-xs" : "prose-sm";
525
- const isPlainText = !effectiveCustomComponents && !hasMarkdownSyntax(displayContent);
548
+ const customComponentsBeyondLinks = React6__default.default.useMemo(() => {
549
+ if (!customComponents) return false;
550
+ return Object.keys(customComponents).some((k) => k !== "a");
551
+ }, [customComponents]);
552
+ const isPlainText = plainText !== void 0 ? plainText : !customComponentsBeyondLinks && looksLikePlainProse(displayContent);
526
553
  if (isPlainText) {
527
554
  return /* @__PURE__ */ jsxRuntime.jsxs(
528
- "span",
555
+ "div",
529
556
  {
530
- className: `${textSizeClass} leading-7 break-words whitespace-pre-line font-light ${className}`,
557
+ className: `${textSizeClass} leading-snug break-words whitespace-pre-wrap ${className}`,
531
558
  children: [
532
559
  displayContent,
533
560
  collapsible && shouldCollapse && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -555,7 +582,16 @@ var MarkdownMessage = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
555
582
  className: `
556
583
  prose ${proseClass} max-w-none break-words overflow-hidden ${textSizeClass}
557
584
  ${isUser ? "prose-invert" : "dark:prose-invert"}
558
- [&>*]:leading-7
585
+ [&>*]:leading-relaxed
586
+ [&>*:first-child]:mt-0 [&>*:last-child]:mb-0
587
+ [&_p]:my-2
588
+ [&_ul]:my-2 [&_ol]:my-2 [&_ul]:pl-5 [&_ol]:pl-5
589
+ [&_li]:my-1 [&_li>p]:my-0
590
+ [&_pre]:my-3
591
+ [&_h1]:mt-4 [&_h1]:mb-2 [&_h1]:text-base [&_h1]:font-semibold
592
+ [&_h2]:mt-3.5 [&_h2]:mb-1.5 [&_h2]:text-[15px] [&_h2]:font-semibold
593
+ [&_h3]:mt-3 [&_h3]:mb-1 [&_h3]:text-sm [&_h3]:font-medium
594
+ [&_h4]:mt-3 [&_h4]:mb-1 [&_h4]:text-sm [&_h4]:font-medium
559
595
  `,
560
596
  style: {
561
597
  // Inherit colors from parent — fixes issues with external
@@ -1541,5 +1577,5 @@ exports.toMarkdown = toMarkdown;
1541
1577
  exports.toRawJson = toRawJson;
1542
1578
  exports.useCollapsibleContent = useCollapsibleContent;
1543
1579
  exports.usePlaygroundContext = usePlaygroundContext;
1544
- //# sourceMappingURL=chunk-SEXWBCLX.cjs.map
1545
- //# sourceMappingURL=chunk-SEXWBCLX.cjs.map
1580
+ //# sourceMappingURL=chunk-PFKR6ZPZ.cjs.map
1581
+ //# sourceMappingURL=chunk-PFKR6ZPZ.cjs.map